Merge branch 'develop' into features/mchmmer
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 11 May 2018 11:25:16 +0000 (12:25 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 11 May 2018 11:25:16 +0000 (12:25 +0100)
136 files changed:
examples/uniref50.hmm [new file with mode: 0644]
help/help.jhm
help/helpTOC.xml
help/html/features/preferences.html
help/html/menus/alwhmmer.html [new file with mode: 0644]
resources/lang/Messages.properties
resources/lang/Messages_es.properties
schemas/jalview.xsd
src/jalview/analysis/AAFrequency.java
src/jalview/analysis/SeqsetUtils.java
src/jalview/api/AlignCalcWorkerI.java
src/jalview/api/AlignViewportI.java
src/jalview/appletgui/AlignFrame.java
src/jalview/appletgui/AlignViewport.java
src/jalview/appletgui/AlignmentPanel.java
src/jalview/appletgui/AnnotationLabels.java
src/jalview/appletgui/OverviewPanel.java
src/jalview/appletgui/SeqPanel.java
src/jalview/bin/Jalview.java
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentAnnotation.java
src/jalview/datamodel/AlignmentI.java
src/jalview/datamodel/AlignmentOrder.java
src/jalview/datamodel/AnnotatedCollectionI.java
src/jalview/datamodel/HMMNode.java [new file with mode: 0644]
src/jalview/datamodel/HiddenMarkovModel.java [new file with mode: 0644]
src/jalview/datamodel/ResidueCount.java
src/jalview/datamodel/Sequence.java
src/jalview/datamodel/SequenceCollectionI.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/datamodel/SequenceI.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/CalculationChooser.java
src/jalview/gui/ColourMenuHelper.java
src/jalview/gui/Desktop.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/Jalview2XML_V1.java
src/jalview/gui/JvSwingUtils.java
src/jalview/gui/OptsAndParamsPage.java
src/jalview/gui/OverviewPanel.java
src/jalview/gui/PairwiseAlignPanel.java
src/jalview/gui/PopupMenu.java
src/jalview/gui/Preferences.java
src/jalview/gui/SeqPanel.java
src/jalview/gui/SplitFrame.java
src/jalview/gui/WsJobParameters.java
src/jalview/gui/WsParamSetManager.java
src/jalview/hmmer/HMMAlign.java [new file with mode: 0644]
src/jalview/hmmer/HMMBuild.java [new file with mode: 0644]
src/jalview/hmmer/HMMERParamStore.java [new file with mode: 0644]
src/jalview/hmmer/HMMERPreset.java [new file with mode: 0644]
src/jalview/hmmer/HMMSearch.java [new file with mode: 0644]
src/jalview/hmmer/HmmerCommand.java [new file with mode: 0644]
src/jalview/io/AlignFile.java
src/jalview/io/FileFormat.java
src/jalview/io/FileLoader.java
src/jalview/io/HMMFile.java [new file with mode: 0644]
src/jalview/io/IdentifyFile.java
src/jalview/io/StockholmFile.java
src/jalview/jbgui/GAlignFrame.java
src/jalview/jbgui/GPreferences.java
src/jalview/jbgui/GRestInputParamEditDialog.java
src/jalview/jbgui/GRestServiceEditorPane.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/renderer/ResidueShaderI.java
src/jalview/schemabinding/version2/JSeq.java
src/jalview/schemabinding/version2/descriptors/JSeqDescriptor.java
src/jalview/schemes/HmmerColourScheme.java [new file with mode: 0644]
src/jalview/schemes/HmmerGlobalBackground.java [new file with mode: 0644]
src/jalview/schemes/HmmerLocalBackground.java [new file with mode: 0644]
src/jalview/schemes/JalviewColourScheme.java
src/jalview/schemes/ResidueProperties.java
src/jalview/util/FileUtils.java [new file with mode: 0644]
src/jalview/util/HMMProbabilityDistributionAnalyser.java [new file with mode: 0644]
src/jalview/util/MapList.java
src/jalview/util/MappingUtils.java
src/jalview/util/Platform.java
src/jalview/util/ProbabilityAnalyserKickstarter.java [new file with mode: 0644]
src/jalview/viewmodel/AlignmentViewport.java
src/jalview/workers/AlignCalcManager.java
src/jalview/workers/ConsensusThread.java
src/jalview/workers/InformationThread.java [new file with mode: 0644]
src/jalview/ws/jws2/Jws2Client.java
src/jalview/ws/jws2/MsaWSThread.java
src/jalview/ws/params/ValueConstrainI.java
src/jalview/ws/params/simple/BooleanOption.java
src/jalview/ws/params/simple/DoubleParameter.java [new file with mode: 0644]
src/jalview/ws/params/simple/IntegerParameter.java
src/jalview/ws/params/simple/LogarithmicParameter.java [new file with mode: 0644]
src/jalview/ws/params/simple/Option.java
src/jalview/ws/params/simple/Parameter.java [deleted file]
src/jalview/ws/params/simple/StringChoiceParameter.java
src/jalview/ws/params/simple/StringParameter.java [new file with mode: 0644]
test/jalview/analysis/AAFrequencyTest.java
test/jalview/analysis/scoremodels/FeatureDistanceModelTest.java
test/jalview/datamodel/AlignmentTest.java
test/jalview/datamodel/AlignmentViewTest.java
test/jalview/datamodel/HMMNodeTest.java [new file with mode: 0644]
test/jalview/datamodel/HiddenMarkovModelTest.java [new file with mode: 0644]
test/jalview/datamodel/HiddenSequencesTest.java
test/jalview/datamodel/ResidueCountTest.java
test/jalview/datamodel/SequenceGroupTest.java
test/jalview/gui/AlignFrameTest.java
test/jalview/gui/AlignViewportTest.java
test/jalview/gui/PairwiseAlignmentPanelTest.java
test/jalview/gui/SequenceRendererTest.java
test/jalview/hmmer/HMMERTest.java [new file with mode: 0644]
test/jalview/hmmer/testProps.jvprops [new file with mode: 0644]
test/jalview/io/FileFormatsTest.java
test/jalview/io/FormatAdapterTest.java
test/jalview/io/HMMFileTest.java [new file with mode: 0644]
test/jalview/io/JSONFileTest.java
test/jalview/io/Jalview2xmlTests.java
test/jalview/io/StockholmFileTest.java
test/jalview/io/test_MADE1_hmm.txt [new file with mode: 0644]
test/jalview/io/test_PKinase_hmm.txt [new file with mode: 0644]
test/jalview/io/test_fn3_hmm.txt [new file with mode: 0644]
test/jalview/renderer/OverviewResColourFinderTest.java
test/jalview/renderer/ResidueColourFinderTest.java
test/jalview/renderer/ScaleRendererTest.java
test/jalview/renderer/seqfeatures/FeatureColourFinderTest.java
test/jalview/schemes/ClustalxColourSchemeTest.java
test/jalview/schemes/HmmerGlobalBackgroundTest.java [new file with mode: 0644]
test/jalview/schemes/HmmerLocalBackgroundTest.java [new file with mode: 0644]
test/jalview/schemes/PIDColourSchemeTest.java
test/jalview/util/Binned.csv [new file with mode: 0644]
test/jalview/util/HMMProbabilityDistributionAnalyserTest.java [new file with mode: 0644]
test/jalview/util/MapListTest.java
test/jalview/util/MappingUtilsTest.java
test/jalview/util/Raw.csv [new file with mode: 0644]
test/jalview/util/test_Fams_for_probability_analysis [new file with mode: 0644]
test/jalview/util/test_hmms_for_probability_analysis [new file with mode: 0644]
test/jalview/ws/gui/Jws2ParamView.java
utils/i18nAnt.xml

diff --git a/examples/uniref50.hmm b/examples/uniref50.hmm
new file mode 100644 (file)
index 0000000..b07ec14
--- /dev/null
@@ -0,0 +1,466 @@
+HMMER3/f [3.1b2 | February 2015]
+NAME  uniref50
+LENG  148 
+ALPH  amino
+ RF    no
+MM    no
+CONS  yes
+CS    no
+MAP   yes
+DATE  Mon Jun 12 14:32:05 2017
+NSEQ  15
+EFFN  0.648193
+CKSUM 2563184735
+STATS LOCAL MSV      -10.0682  0.70956
+STATS LOCAL VITERBI  -10.7870  0.70956
+STATS LOCAL FORWARD   -4.6837  0.70956
+HMM          A        C        D        E        F        G        H        I        K        L        M        N        P        Q        R        S        T        V        W        Y   
+            m->m     m->i     m->d     i->m     i->i     d->m     d->d
+  COMPO   2.40816  3.71583  2.80837  2.63551  3.47092  2.77036  3.85028  2.88279  2.80267  2.53589  3.68425  3.22102  3.34428  3.14560  3.11474  2.53177  2.75990  2.58070  5.00144  3.51101
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.10433  3.97705  2.52157  0.61958  0.77255  0.00000        *
+      1   2.99317  4.53706  4.08224  3.67789  3.22093  3.85692  4.40592  2.39958  3.44433  1.81088  1.32037  3.95163  4.31759  3.82413  3.64608  3.34553  3.29902  2.40928  5.06591  3.83044      1 m - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+      2   0.97044  4.20710  3.49350  3.28598  4.08269  3.03087  4.30444  3.21278  3.30302  3.09300  4.12129  3.42792  3.77296  3.64134  3.55157  2.55705  2.83652  2.86187  5.50678  4.31039      2 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.11955  3.90315  2.38048  0.61958  0.77255  0.55549  0.85282
+      3   1.74035  4.09199  3.34495  3.00819  4.05288  2.91638  4.05509  3.33461  3.01251  3.11462  3.97728  3.20348  3.62940  3.32849  3.32799  1.99191  1.99086  2.89563  5.42641  4.20726      3 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03323  3.81683  4.53917  0.61958  0.77255  0.62561  0.76558
+      4   2.37663  4.18625  3.55838  3.17855  3.75132  3.18264  4.13666  2.64341  3.07328  2.62344  3.69712  3.39774  3.83139  3.44405  3.35689  2.61052  1.64486  2.15973  5.30034  4.05468      4 t - - -
+          2.68617  4.42230  2.77525  2.73129  3.46359  2.40511  3.72500  3.29359  2.67746  2.69350  4.24695  2.90352  2.73719  3.18152  2.89806  2.37885  2.77501  2.98524  4.58482  3.61508
+          0.33937  1.47682  2.82312  0.71438  0.67236  0.50642  0.92294
+      5   1.78828  4.31568  3.18846  2.75366  3.97645  3.11838  3.84000  3.34055  2.67250  3.02453  3.87541  3.10729  3.71676  3.06391  2.67828  2.15246  2.50645  2.96422  5.30410  4.05011      9 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03188  3.85742  4.57976  0.61958  0.77255  0.59400  0.80322
+      6   2.60146  4.34120  4.20318  3.64233  3.23200  4.03946  4.38229  1.91078  3.53317  1.46276  2.80385  3.95250  4.35454  3.78680  3.77614  3.34686  3.12310  1.90138  5.05979  3.90282     10 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03188  3.85742  4.57976  0.61958  0.77255  0.59400  0.80322
+      7   2.51618  4.38929  3.20785  2.68482  3.53842  3.39630  3.71025  2.97988  2.63127  2.66315  3.23915  3.11866  3.35060  2.98059  3.01133  2.11689  2.77574  2.72369  4.95633  3.10650     11 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03188  3.85742  4.57976  0.61958  0.77255  0.59400  0.80322
+      8   1.83112  4.12334  3.20156  2.95461  4.23963  1.79514  4.09699  3.64646  3.07597  3.33878  4.16582  3.16397  3.61350  3.35846  3.40724  1.96001  2.64648  3.10558  5.57497  4.34818     12 g - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.07518  3.85742  2.97012  0.61958  0.77255  0.59400  0.80322
+      9   2.02467  4.19921  3.47207  3.00878  3.03795  3.27081  3.95597  2.70270  2.96218  2.55248  3.54468  3.31239  3.83177  3.27950  3.28895  2.63385  2.09090  2.46488  5.06606  3.80489     13 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03327  3.81551  4.53786  0.61958  0.77255  0.56041  0.84624
+     10   2.25155  4.19461  3.85704  3.29295  2.92371  3.72128  4.04839  2.07964  3.20853  2.08962  2.71310  3.60847  4.09120  3.47607  3.47945  3.00735  2.74040  2.14097  4.86082  3.65928     14 i - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03170  3.86316  4.58551  0.61958  0.77255  0.53107  0.88667
+     11   2.97746  4.34766  4.53309  3.96552  2.78843  4.21079  4.53997  1.80103  3.85948  1.59494  2.57669  4.20401  4.48099  4.02954  4.02513  3.53069  3.20806  1.63119  5.03312  3.89134     15 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     12   2.01604  4.15364  3.23013  2.99255  4.26101  2.66741  4.12859  3.66796  3.09383  3.37186  4.20680  3.19709  3.64453  3.39377  3.41395  1.27425  2.68165  3.13093  5.59931  4.36607     16 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     13   2.41396  4.26265  3.40226  2.93569  3.72492  3.24366  3.92462  2.93397  2.83929  2.73560  3.16052  3.25846  3.81309  3.20648  3.16819  2.37913  1.73294  2.65776  5.16309  3.91530     17 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     14   2.06589  4.14828  3.30608  3.02868  4.20053  2.92394  4.12227  3.52677  3.06750  3.27902  4.13704  3.22373  3.65849  3.38850  3.37961  1.31011  2.40891  3.04032  5.55736  4.32788     18 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     15   2.74009  4.29274  3.92243  3.42912  1.74599  3.72053  3.90473  2.32427  3.32349  2.18956  3.31553  3.65797  4.14118  3.57919  3.55745  2.71376  3.01017  2.38146  4.46330  2.97696     19 f - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     16   2.76094  4.39380  4.31945  3.75589  3.18422  4.12530  4.45889  2.01307  3.63847  1.30728  2.59228  4.05575  4.41925  3.86957  3.85970  3.43754  3.19324  1.94550  5.06650  3.93230     20 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     17   2.70295  4.73637  3.16526  2.68917  4.18427  3.37581  3.71759  3.61851  2.27125  3.18722  4.06871  3.11427  2.39752  2.89725  1.66361  2.77186  2.98335  3.28411  5.34221  4.10051     21 r - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.07762  3.90315  2.90945  0.61958  0.77255  0.55549  0.85282
+     18   2.49055  4.81399  3.14505  2.59164  4.19520  3.44406  3.60132  3.55142  1.92611  3.12799  3.98038  3.04037  3.86298  2.75679  1.83484  2.76119  2.76042  3.23493  5.31169  4.06564     22 r - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.06501  3.85742  3.17445  0.61958  0.77255  0.59400  0.80322
+     19   2.43450  4.81939  2.81703  2.39298  4.15804  3.33308  3.59871  3.56807  2.06609  3.14527  3.97247  2.89702  3.36070  2.29211  2.66793  2.54254  2.87166  3.22778  5.35034  4.03520     23 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03294  3.82535  4.54770  0.61958  0.77255  0.61916  0.77305
+     20   2.61608  4.67386  2.79167  2.51004  4.07010  3.23635  3.73836  3.55025  2.48903  3.13320  4.04098  2.97430  2.02723  2.34075  2.83811  2.68076  2.93097  3.21608  5.34739  4.03735     24 p - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03294  3.82535  4.54770  0.61958  0.77255  0.51069  0.91649
+     21   1.83080  4.22890  3.60014  3.08598  3.61014  3.38577  4.01761  2.55536  3.00939  2.52819  3.20189  3.39791  3.91288  3.33215  3.33591  2.72706  2.41446  2.12040  5.12303  3.89826     25 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     22   2.43845  4.29437  3.39983  3.04145  3.80350  3.19872  4.06195  2.96220  2.98493  2.76612  3.80233  3.32666  1.71751  3.35496  3.29387  2.63325  2.83846  2.21304  5.28839  4.02321     26 p - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     23   2.55648  4.28453  3.47615  2.92649  3.45346  3.51308  3.86072  2.37030  2.85167  2.40896  2.93550  3.31525  2.97437  3.17776  3.19434  2.79032  2.33896  2.42929  4.94762  3.71651     27 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     24   2.23005  4.31546  3.25841  2.77512  3.78441  3.22479  3.82985  3.12652  2.73582  2.83244  3.03171  3.14960  3.26067  3.07830  3.10838  1.85715  2.73859  2.81468  5.16957  3.91289     28 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     25   2.72216  3.51794  4.14734  3.58168  3.26953  3.85722  4.23682  2.10046  3.47012  1.71220  2.91412  3.83361  4.22096  3.71804  3.68973  3.16541  2.79579  1.71693  4.93656  3.75086     29 l - - -
+          2.68606  4.42227  2.77522  2.73126  3.46337  2.40515  3.72497  3.29356  2.67743  2.69357  4.24692  2.90349  2.73742  3.18149  2.89784  2.37889  2.77522  2.98521  4.58479  3.61506
+          0.31572  1.55442  2.82310  0.27619  1.42159  0.55549  0.85282
+     26   2.06718  4.47388  3.00085  2.59301  4.03403  3.18938  3.75234  3.40130  2.21691  3.06406  3.90876  3.01767  3.74194  2.94856  2.91976  2.09488  2.60568  3.04014  5.32541  4.04568     31 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03205  3.85226  4.57460  0.61958  0.77255  0.52495  0.89548
+     27   2.09937  4.25808  3.35967  2.86682  3.65405  3.28224  3.85971  2.93650  2.81278  2.15397  3.59474  3.22143  3.43624  3.14697  3.16235  2.43009  2.43628  2.66078  5.07593  3.83686     32 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     28   2.56380  4.32380  3.45039  2.92280  3.52453  3.48960  3.88793  2.33272  2.83649  2.29194  3.45598  3.31192  2.56007  3.18425  3.18050  2.78603  2.52825  2.43071  5.02605  3.78340     33 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     29   2.52137  4.41862  3.18708  2.64701  3.24265  3.41116  3.70401  2.99879  2.50849  2.54033  3.56040  3.09794  3.19241  2.94883  3.00442  2.32271  2.53579  2.73855  5.01724  3.74765     34 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     30   2.00013  4.58033  2.94855  2.53646  4.07584  3.24271  3.72285  3.46598  2.50253  3.10366  3.94143  2.28591  3.76727  2.90505  2.65085  2.58556  2.61842  3.10852  5.34830  4.05040     35 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     31   2.38233  4.27978  3.41241  2.86526  3.23400  3.48475  3.81694  2.67786  2.81404  2.37039  3.42629  2.84230  3.90072  3.13098  3.17039  2.75440  2.50322  2.16090  4.92926  3.68461     36 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     32   2.57741  4.71210  2.95136  2.48036  4.10354  2.51445  3.64563  3.50876  2.11219  3.10615  3.93363  2.96219  3.79067  2.80786  2.54902  2.50592  2.51289  3.16566  5.32824  4.02677     37 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     33   2.48649  4.79372  2.91636  2.20828  4.05411  3.38774  3.59403  3.46081  2.32653  3.05709  3.87988  2.78811  3.79502  2.48988  2.50461  2.63652  2.83744  2.71303  5.28703  3.96685     38 e - - -
+          2.68619  4.42226  2.77520  2.73124  3.46338  2.40514  3.72495  3.29355  2.67742  2.69356  4.24691  2.90348  2.73732  3.18147  2.89802  2.37888  2.77520  2.98519  4.58478  3.61504
+          0.07101  2.83445  4.62550  0.63888  0.75053  0.55549  0.85282
+     34   1.61247  4.12982  3.30077  3.01153  4.23531  2.30721  4.11812  3.64225  3.09602  3.33089  4.15414  3.20546  3.63382  3.37908  3.42786  1.71494  2.65404  3.10635  5.57312  4.35188     41 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     35   2.72153  4.23229  3.98871  3.42694  2.97156  3.37228  4.12428  2.11066  3.32720  1.56866  3.14804  3.72158  4.17041  3.58506  3.57523  3.10753  2.96236  2.01957  4.85619  3.63474     42 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     36   2.59948  4.33296  4.13320  3.58598  1.90470  3.92561  4.14661  2.31847  3.46961  1.74381  2.73954  3.84829  4.26638  3.69996  3.68809  3.23462  3.08833  2.27549  4.71854  3.39100     43 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     37   2.58931  4.58161  2.85848  2.66250  4.27569  1.35942  3.92193  3.72667  2.37699  3.36968  4.25453  3.08080  3.80217  3.15095  3.05968  2.68693  2.97358  3.32002  5.50315  4.25822     44 g - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     38   2.65443  4.41996  3.43781  2.92526  3.49579  3.52457  3.83449  2.83057  2.64507  1.65492  3.47551  3.30970  3.36731  3.12885  2.65176  2.85231  2.91346  2.65496  4.98654  3.73087     45 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     39   2.72350  4.79628  3.09209  2.60253  4.10688  3.43694  3.64699  3.48037  1.53491  2.80300  3.97997  3.05455  3.87955  2.81812  2.48623  2.53142  2.96661  3.17965  5.30004  4.01932     46 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     40   1.82674  4.13179  3.37396  3.04098  4.15468  2.93287  4.10316  3.48191  3.05943  3.22685  4.07364  3.23234  3.65478  3.36800  3.38156  1.54612  2.23418  3.00585  5.51189  4.29184     47 s - - -
+          2.68618  4.42225  2.77520  2.73124  3.46354  2.40513  3.72495  3.29354  2.67741  2.69355  4.24690  2.90347  2.73740  3.18147  2.89801  2.37887  2.77520  2.98508  4.58477  3.61503
+          0.07101  2.83445  4.62550  0.49418  0.94179  0.55549  0.85282
+     41   1.87334  4.14690  3.25058  2.97809  4.26468  2.12605  4.11046  3.68104  3.08263  3.36184  4.18261  3.18779  3.63442  3.36584  3.42015  1.58161  2.66271  3.13490  5.59481  4.36766     49 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.11955  3.90315  2.38048  0.61958  0.77255  0.55549  0.85282
+     42   2.21070  4.25592  3.22113  2.77420  3.85340  3.11965  3.84389  3.18555  2.74438  2.69874  3.77079  3.12117  3.16635  3.08826  3.10948  2.13243  2.17697  2.83916  5.22265  3.97074     50 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03323  3.81683  4.53917  0.61958  0.77255  0.62561  0.76558
+     43   2.34367  4.62113  3.10732  2.54725  3.88271  3.41056  3.61301  3.25335  2.12788  2.89080  3.32993  3.01581  3.81452  2.79680  2.35592  2.55841  2.82420  2.96607  5.15612  3.88260     51 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.07842  3.81683  2.92953  0.61958  0.77255  0.50642  0.92294
+     44   2.82371  4.84862  3.20218  2.72371  4.21308  3.44211  3.65714  3.71157  2.07944  3.25434  4.14899  2.84303  3.91564  2.83614  1.36807  2.87376  3.07618  3.38687  5.31229  4.06004     52 r - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.12129  3.86316  2.37274  0.61958  0.77255  0.58934  0.80899
+     45   2.50307  4.57358  2.77436  2.48515  4.13002  2.10145  3.72113  3.58708  2.48196  3.19739  4.04544  2.56817  3.72971  2.91621  2.54565  2.57756  2.84032  3.19983  5.38083  4.07634     53 g - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03462  3.77648  4.49883  0.61958  0.77255  0.55399  0.85485
+     46   2.68547  4.96255  2.09111  2.21584  4.36925  1.97687  3.70446  3.84410  2.62382  3.41713  4.25934  2.75900  3.76266  2.58919  3.12019  2.66938  2.98839  3.45462  5.60805  4.21173     54 g - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03205  3.85226  4.57460  0.61958  0.77255  0.52495  0.89548
+     47   2.70472  4.70735  3.22145  2.64799  3.96742  3.15410  3.63371  3.33902  2.12091  2.43520  3.82970  3.09240  3.88741  2.81708  1.91192  2.78290  2.92703  3.06076  5.19463  3.94224     55 r - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     48   2.39251  4.23853  3.75245  3.18839  3.35715  3.69117  4.01036  2.17738  3.07061  2.00722  3.28706  3.53429  4.07078  3.39072  3.07752  2.97399  2.89120  1.85844  4.92824  3.71532     56 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     49   2.56050  4.39105  3.34411  2.78319  3.60155  3.46480  3.77128  2.83822  2.62742  2.58594  3.21262  3.20237  3.88486  3.03059  2.56448  2.73642  2.19035  2.37832  5.02624  3.77891     57 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     50   1.37812  2.80072  3.83498  3.42070  3.87397  2.99921  4.24161  2.96530  3.32256  2.89459  3.81917  3.44880  3.71764  3.60422  3.56604  2.43360  2.40411  2.61888  5.33835  4.15246     58 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.55549  0.85282
+     51   2.74532  4.50724  3.42983  2.95244  3.42568  3.60626  3.88910  2.77026  2.70375  2.22807  1.95486  3.35569  4.02547  2.58121  2.99178  2.94186  2.99694  2.66631  5.01046  3.74777     59 m - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03044  3.90315  4.62550  0.61958  0.77255  0.44450  1.02483
+     52   0.87297  4.24657  3.57075  3.36786  4.15839  3.06811  4.37727  3.29971  3.38685  3.17640  4.19749  3.49040  3.81731  3.71861  3.62959  2.59634  2.88098  2.93600  5.57511  4.38724     60 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     53   1.96298  4.17134  3.43460  3.07855  4.14627  2.98936  4.12481  3.46945  3.08161  3.21642  4.06614  3.27556  3.70074  3.39215  3.40515  1.84467  1.63498  3.01250  5.50977  4.28998     61 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     54   3.40066  4.84720  3.99369  3.74344  2.30278  3.95279  3.67128  3.39553  3.59798  2.82228  4.05988  3.85394  4.42456  3.87882  3.75994  3.52665  3.68805  3.27113  3.95029  0.80817     62 y - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     55   2.86663  5.06853  2.87640  2.51952  4.45748  3.43879  3.66568  3.89866  1.33937  3.41664  4.27179  2.44223  3.91577  2.81805  2.46217  2.85914  3.10555  3.54515  5.50478  4.21799     63 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     56   2.89101  4.40561  4.26922  3.93641  3.62800  3.83108  4.72052  2.04974  3.80577  2.29743  3.57810  4.10920  4.38636  4.15841  4.00806  3.34183  3.25039  0.90272  5.42983  4.16757     64 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     57   2.78989  4.87427  3.10728  2.66228  4.33471  3.44160  3.70636  3.64306  1.30828  3.25641  4.14609  3.10047  3.92071  2.86764  2.46119  2.83588  2.59339  3.32217  5.44317  4.19498     65 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     58   3.28295  4.64373  4.65267  4.15432  2.12281  4.39226  4.40565  2.30868  4.01063  0.99404  2.96208  4.34589  4.63887  4.13687  4.14117  3.75853  3.51440  2.42033  4.68321  3.26182     66 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     59   3.08248  4.42168  4.72065  4.23378  3.50231  4.37831  4.95293  1.13074  4.10572  1.99571  3.31982  4.46032  4.70821  4.37869  4.30619  3.77127  3.35421  1.44848  5.47660  4.27063     67 i - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     60   2.47137  4.31634  3.52340  3.28135  4.06362  3.15188  4.29038  3.20358  3.22639  3.06334  4.10788  3.47324  3.86421  3.61618  3.47946  2.67390  1.00625  2.88730  5.49222  4.28053     68 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     61   2.89484  4.63395  3.51346  3.36817  4.35306  3.31558  4.43642  3.92611  3.43456  3.54133  4.59617  3.66397  0.65427  3.82016  3.66760  3.06578  3.34480  3.55944  5.51022  4.47541     69 P - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     62   2.83547  5.32344  1.90710  1.42799  4.63051  3.24198  3.71244  4.09996  2.65068  3.63347  4.46321  2.71732  3.81726  2.86723  3.20067  2.75440  2.81778  3.69487  5.81218  4.35094     70 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     63   2.79923  4.56350  3.49435  3.40744  4.54632  0.58454  4.52062  4.17205  3.60289  3.81287  4.79002  3.65874  3.95796  3.91884  3.82676  2.97427  3.28861  3.68020  5.61312  4.65200     71 G - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     64   2.69344  5.03834  2.59685  1.78499  4.35492  3.31996  3.63904  3.79867  2.33359  3.34661  4.15382  2.64678  2.71516  2.78054  2.89199  2.67010  2.77928  3.42501  5.53498  4.15652     72 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     65   2.70271  4.40317  3.56325  3.00957  3.45446  3.68235  3.94694  2.18180  2.88182  2.21283  3.37093  3.41883  4.05792  2.33611  3.21378  2.95204  2.94041  2.01647  5.02429  3.78732     73 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     66   3.04481  5.17464  2.53544  0.88540  4.53437  3.34332  3.94029  4.00914  2.83416  3.60986  4.58016  2.99593  3.95313  3.15433  3.25317  3.01711  3.35013  3.68253  5.68627  4.40959     74 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     67   3.05681  4.44153  4.54138  3.99838  1.97987  4.22221  4.40129  2.17878  3.87522  1.45215  3.02589  4.20160  4.50632  4.03401  4.02978  3.55251  3.29207  1.80812  4.80289  3.46847     75 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     68   2.82984  5.35567  1.99168  1.57663  4.64578  3.25717  3.68509  4.14274  2.58330  3.63869  4.45307  2.71724  3.81329  2.22362  3.11653  2.74299  3.09347  3.72626  5.79564  4.33600     76 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     69   2.50977  1.62448  4.23724  3.80750  3.60189  3.40590  4.45756  2.35254  3.63764  2.45765  3.57920  3.82230  4.04603  3.92585  3.81907  2.84633  2.91668  1.82275  5.24689  4.01880     77 c - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     70   2.77571  5.11398  2.10801  2.05696  4.45701  3.25620  3.72899  3.91339  2.64389  3.48166  4.32027  2.78446  1.86353  2.89484  3.15510  2.73789  3.05806  3.53410  5.67671  4.27030     78 p - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     71   2.91274  5.42662  1.24765  1.93231  4.73792  3.20738  3.76458  4.24169  2.78531  3.76893  4.62568  2.68636  3.83308  2.93581  3.37349  2.60161  3.20907  3.82383  5.94007  4.44265     79 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     72   2.93000  5.34144  1.08347  2.15883  4.66482  3.19912  3.82811  4.25255  2.88821  3.80850  4.69751  2.51974  3.85217  3.02158  3.46889  2.84580  3.25390  3.83179  5.90365  4.41772     80 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     73   2.89101  4.40561  4.26922  3.93641  3.62800  3.83108  4.72052  2.04974  3.80577  2.29743  3.57810  4.10920  4.38636  4.15841  4.00806  3.34183  3.25039  0.90272  5.42983  4.16757     81 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     74   3.40066  4.84720  3.99369  3.74344  2.30278  3.95279  3.67128  3.39553  3.59798  2.82228  4.05988  3.85394  4.42456  3.87882  3.75994  3.52665  3.68805  3.27113  3.95029  0.80817     82 y - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     75   3.08173  4.41570  4.73343  4.24332  3.51344  4.38931  4.96241  1.16063  4.11994  2.00857  3.32756  4.46929  4.71466  4.39012  4.32070  3.78014  3.35186  1.39369  5.48545  4.28088     83 i - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     76   3.27378  4.70553  4.35708  3.99825  3.17780  4.11433  4.62122  2.38848  3.76496  0.75643  3.16963  4.26355  4.53226  4.10824  3.92358  3.69863  3.56359  2.45281  5.09417  3.84135     84 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     77   3.10426  5.24570  0.77891  2.40498  4.63731  3.29196  4.02650  4.24977  3.13093  3.83985  4.82107  2.96628  3.95224  3.26642  3.66070  3.05541  3.44536  3.87811  5.78539  4.49402     85 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     78   2.10165  4.63153  3.04360  2.53313  3.37849  3.42468  3.14974  3.24484  2.48640  2.87927  3.73924  3.02051  3.83549  2.34761  2.89722  2.67591  2.83487  2.96227  5.11406  3.77860     86 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     79   0.87297  4.24657  3.57075  3.36786  4.15839  3.06811  4.37727  3.29971  3.38685  3.17640  4.19749  3.49040  3.81731  3.71861  3.62959  2.59634  2.88098  2.93600  5.57511  4.38724     87 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     80   3.04481  5.17464  2.53544  0.88540  4.53437  3.34332  3.94029  4.00914  2.83416  3.60986  4.58016  2.99593  3.95313  3.15433  3.25317  3.01711  3.35013  3.68253  5.68627  4.40959     88 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     81   3.04481  5.17464  2.53544  0.88540  4.53437  3.34332  3.94029  4.00914  2.83416  3.60986  4.58016  2.99593  3.95313  3.15433  3.25317  3.01711  3.35013  3.68253  5.68627  4.40959     89 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     82   2.02804  4.79412  2.56696  2.04470  4.09359  3.33689  3.67081  3.44631  2.51465  3.10781  3.94410  2.90500  3.80252  2.83547  2.98166  2.64658  2.87169  2.76307  5.37415  4.03168     90 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     83   2.79923  4.56350  3.49435  3.40744  4.54632  0.58454  4.52062  4.17205  3.60289  3.81287  4.79002  3.65874  3.95796  3.91884  3.82676  2.97427  3.28861  3.68020  5.61312  4.65200     91 G - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     84   2.73428  4.33692  3.73213  3.19478  3.16177  3.72868  2.92126  1.73180  3.00305  2.10225  3.32627  3.53324  4.10443  3.37488  3.27326  3.02489  2.97120  2.37844  4.75364  3.40581     92 i - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     85   2.98626  5.46880  1.08491  1.97249  4.77077  3.21550  3.81546  4.28421  2.87189  3.82944  4.72170  2.71026  3.86087  3.00007  3.46540  2.87647  3.29141  3.87860  5.96770  4.48798     93 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     86   3.27378  4.70553  4.35708  3.99825  3.17780  4.11433  4.62122  2.38848  3.76496  0.75643  3.16963  4.26355  4.53226  4.10824  3.92358  3.69863  3.56359  2.45281  5.09417  3.84135     94 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     87   2.89484  4.63395  3.51346  3.36817  4.35306  3.31558  4.43642  3.92611  3.43456  3.54133  4.59617  3.66397  0.65427  3.82016  3.66760  3.06578  3.34480  3.55944  5.51022  4.47541     95 P - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     88   3.48726  4.82741  4.35628  4.01269  1.82549  4.23514  3.48811  3.25093  3.87322  2.62544  3.87831  3.93991  4.57991  3.96204  3.99151  3.61127  3.72377  3.16284  3.67256  0.95290     96 y - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     89   2.36871  4.29005  3.29968  3.12112  4.18153  3.01810  4.22768  3.71868  3.20194  3.43114  4.34903  3.32859  3.76571  3.54324  3.48419  0.94365  2.85682  3.23083  5.54583  4.26583     97 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     90   2.70964  0.75093  4.25205  4.01610  3.98428  3.30982  4.64026  3.14621  3.84384  3.05665  4.18165  3.97525  4.02496  4.18572  3.94943  2.98138  3.18527  2.88356  5.37752  4.27103     98 c - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     91   3.12574  4.95602  3.62729  3.11760  4.33719  3.59265  3.90370  3.88680  2.28467  3.38377  4.38192  3.46899  4.09078  3.11945  0.82993  3.20529  3.38498  3.60641  5.37824  4.24257     99 r - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     92   0.87297  4.24657  3.57075  3.36786  4.15839  3.06811  4.37727  3.29971  3.38685  3.17640  4.19749  3.49040  3.81731  3.71861  3.62959  2.59634  2.88098  2.93600  5.57511  4.38724    100 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     93   2.79923  4.56350  3.49435  3.40744  4.54632  0.58454  4.52062  4.17205  3.60289  3.81287  4.79002  3.65874  3.95796  3.91884  3.82676  2.97427  3.28861  3.68020  5.61312  4.65200    101 G - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     94   2.36871  4.29005  3.29968  3.12112  4.18153  3.01810  4.22768  3.71868  3.20194  3.43114  4.34903  3.32859  3.76571  3.54324  3.48419  0.94365  2.85682  3.23083  5.54583  4.26583    102 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     95   2.70964  0.75093  4.25205  4.01610  3.98428  3.30982  4.64026  3.14621  3.84384  3.05665  4.18165  3.97525  4.02496  4.18572  3.94943  2.98138  3.18527  2.88356  5.37752  4.27103    103 c - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     96   2.36871  4.29005  3.29968  3.12112  4.18153  3.01810  4.22768  3.71868  3.20194  3.43114  4.34903  3.32859  3.76571  3.54324  3.48419  0.94365  2.85682  3.23083  5.54583  4.26583    104 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     97   2.36871  4.29005  3.29968  3.12112  4.18153  3.01810  4.22768  3.71868  3.20194  3.43114  4.34903  3.32859  3.76571  3.54324  3.48419  0.94365  2.85682  3.23083  5.54583  4.26583    105 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     98   2.70964  0.75093  4.25205  4.01610  3.98428  3.30982  4.64026  3.14621  3.84384  3.05665  4.18165  3.97525  4.02496  4.18572  3.94943  2.98138  3.18527  2.88356  5.37752  4.27103    106 c - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+     99   0.87297  4.24657  3.57075  3.36786  4.15839  3.06811  4.37727  3.29971  3.38685  3.17640  4.19749  3.49040  3.81731  3.71861  3.62959  2.59634  2.88098  2.93600  5.57511  4.38724    107 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    100   2.79923  4.56350  3.49435  3.40744  4.54632  0.58454  4.52062  4.17205  3.60289  3.81287  4.79002  3.65874  3.95796  3.91884  3.82676  2.97427  3.28861  3.68020  5.61312  4.65200    108 G - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    101   3.06946  5.03551  3.25229  2.85531  4.44585  3.54670  3.82012  3.88188  0.90373  3.42461  4.38128  3.27486  4.04036  3.00629  2.45564  3.10509  3.31538  3.58407  5.45821  4.28639    109 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    102   3.06247  4.41039  4.65086  4.13598  3.48324  4.35915  4.85935  1.65561  4.00771  1.89605  3.31161  4.38665  4.67296  4.28428  4.22305  3.72759  3.32396  1.08186  5.42132  4.21018    110 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    103   2.33323  4.28075  3.53672  3.04537  3.62455  3.45748  3.98551  2.58410  2.72399  2.59228  3.55231  3.38781  3.95328  3.30102  3.25844  2.79290  2.46624  1.66085  5.10597  3.87716    111 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    104   2.09904  4.31904  3.13967  2.79512  4.23584  2.43802  3.97520  3.66080  2.88605  3.30435  4.12032  2.79615  3.70254  3.18983  3.27753  1.61859  2.49732  3.17574  5.54095  4.27688    112 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    105   2.79923  4.56350  3.49435  3.40744  4.54632  0.58454  4.52062  4.17205  3.60289  3.81287  4.79002  3.65874  3.95796  3.91884  3.82676  2.97427  3.28861  3.68020  5.61312  4.65200    113 G - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    106   2.34210  4.57052  2.98887  2.43186  3.63497  3.31233  3.71920  3.32573  2.57569  2.97882  3.82112  2.81207  3.79423  2.91349  3.00476  1.86229  2.69145  3.00524  5.25570  3.95436    114 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    107   3.05964  4.41092  4.64145  4.12759  3.48238  4.35054  4.85240  1.66963  3.99735  1.89738  3.31309  4.37857  4.66775  4.27653  4.21363  3.71953  3.32208  1.07763  5.41853  4.20516    115 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    108   2.91005  5.38045  1.25818  2.12941  4.69830  3.20228  3.78776  4.26304  2.81947  3.79137  4.65619  2.14323  3.83796  2.96707  3.40279  2.81725  3.21882  3.83565  5.91563  4.42054    116 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    109   2.96665  4.95377  2.97494  2.73211  4.13599  3.43683  3.89106  3.78353  2.54586  3.27542  4.30113  3.19246  3.99230  1.05904  2.82765  3.01035  3.26391  3.50694  5.38986  4.09082    117 q - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    110   2.64618  4.90499  2.31134  2.18942  4.30332  3.26131  3.70172  3.73572  2.57300  3.32434  4.14511  2.84177  3.78986  2.86174  3.06104  1.76618  2.63178  3.35922  5.54260  4.16860    118 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    111   3.10426  5.24570  0.77891  2.40498  4.63731  3.29196  4.02650  4.24977  3.13093  3.83985  4.82107  2.96628  3.95224  3.26642  3.66070  3.05541  3.44536  3.87811  5.78539  4.49402    119 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    112   2.73269  4.96873  2.61141  2.26957  4.35491  2.17303  3.70728  3.80016  2.46897  3.36392  4.20366  2.88233  3.83451  1.94009  2.87446  2.73151  3.00866  3.43365  5.54626  4.19876    120 q - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    113   2.56630  4.67539  2.76483  2.50324  4.25470  3.20379  3.80042  3.71196  2.47872  3.32135  4.15966  2.47516  3.79205  2.98884  3.00841  1.53662  2.90903  3.30833  5.51362  4.18451    121 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    114   3.45422  4.77029  4.46140  4.11213  1.01250  4.26302  3.55945  3.07075  3.96969  2.40922  3.69615  4.01237  4.59409  4.02617  4.05737  3.63979  3.68916  3.02613  3.73517  1.83750    122 f - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    115   3.27378  4.70553  4.35708  3.99825  3.17780  4.11433  4.62122  2.38848  3.76496  0.75643  3.16963  4.26355  4.53226  4.10824  3.92358  3.69863  3.56359  2.45281  5.09417  3.84135    123 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    116   2.92493  5.35887  1.12201  2.14550  4.68054  3.19834  3.81470  4.26138  2.86788  3.80711  4.68829  2.43062  3.84716  3.00361  3.45124  2.83676  3.24430  3.83759  5.91360  4.42201    124 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02824  3.97705  4.69940  0.61958  0.77255  0.48576  0.95510
+    117   2.99103  5.43832  1.04731  2.03422  4.75036  3.21916  3.83186  4.26509  2.89245  3.82288  4.72422  2.72815  3.86743  3.02108  3.48036  2.88767  3.30065  3.86474  5.95049  4.48470    125 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.05161  3.97705  3.45590  0.61958  0.77255  0.48576  0.95510
+    118   2.86997  5.43069  1.57180  1.74614  4.72729  2.80306  3.71453  4.23943  2.69618  3.73332  4.56237  2.43722  3.80910  2.87126  3.27991  2.76596  3.14983  3.81040  5.89719  4.40314    126 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    119   2.94701  4.93449  2.95833  2.71460  4.11381  3.42085  3.87354  3.75736  2.52981  3.25157  4.27740  3.17495  3.97565  1.09531  2.81227  2.99143  3.24405  3.48203  5.37148  4.07074    127 q - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    120   2.77849  4.28259  3.99549  3.02221  3.34513  3.89873  4.21017  1.60238  3.32583  1.96055  3.04166  3.76188  4.24121  3.61775  3.59603  3.18793  3.01465  1.89778  5.01613  3.81900    128 i - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    121   2.05663  4.99383  2.42035  1.95337  4.30142  3.11016  3.64379  3.74448  2.38547  3.30891  4.11909  2.80952  3.78509  2.79112  2.97996  2.54099  2.92358  3.37653  5.51637  4.13250    129 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    122   2.37074  5.20065  2.03752  1.62561  4.52764  2.94012  3.68254  3.99698  2.59389  3.53203  4.34713  2.73405  3.79399  2.83254  3.13133  2.70217  3.03318  3.59496  5.71621  4.27884    130 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    123   2.76891  4.53595  3.45942  3.36936  4.50963  0.61326  4.48439  4.12940  3.56175  3.77320  4.74981  3.62373  3.92970  3.87945  3.78857  2.94321  3.25651  3.64192  5.58291  4.61439    131 G - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    124   3.45280  4.72560  4.55948  4.18538  1.45983  4.27876  3.45556  3.19175  4.01502  2.56322  3.77632  3.99268  4.58568  4.02082  4.06587  3.62371  3.67122  3.09770  1.76510  1.80304    132 f - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    125   2.87283  4.39315  4.23821  3.90420  3.61058  3.80809  4.69198  2.04849  3.77322  2.28363  3.56364  4.08078  4.36427  4.12727  3.97777  3.31702  3.23254  0.92773  5.40873  4.14528    133 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    126   3.24760  4.68579  4.32075  3.96132  3.16793  4.08580  4.59138  2.37683  3.72825  0.78064  3.16594  4.22883  4.50730  4.07699  3.89079  3.66669  3.53825  2.43535  5.07658  3.81868    134 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    127   2.45786  4.30296  3.50186  3.25812  4.04222  3.13941  4.26905  3.17937  3.20271  3.03994  4.08552  3.45408  3.84975  3.59352  3.45722  2.66008  1.04037  2.86556  5.47283  4.25897    135 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    128   2.68154  0.78852  4.21932  3.97783  3.95068  3.28696  4.60693  3.10838  3.80528  3.02007  4.14415  3.94300  4.00035  4.14805  3.91507  2.95331  3.15521  2.84739  5.34926  4.23772    136 c - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    129   2.02617  4.29048  3.42265  2.94627  3.54036  3.40652  3.31257  2.77872  2.86355  2.59741  3.53948  3.30371  3.90044  3.21666  3.18816  2.73904  2.82169  1.86270  5.00831  3.74432    137 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    130   0.90195  4.23400  3.54659  3.34205  4.13472  3.05626  4.35430  3.27256  3.36043  3.15035  4.17350  3.47069  3.80326  3.69417  3.60509  2.58374  2.86679  2.91280  5.55371  4.36315    138 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    131   3.44381  4.80306  4.30117  3.95207  1.85364  4.19548  3.48537  3.22033  3.81418  2.60484  3.85318  3.90681  4.54641  3.92239  3.94488  3.57229  3.68268  3.12961  3.68006  0.97942    139 y - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    132   2.86235  4.60578  3.47842  3.32948  4.31715  3.28867  4.39999  3.88386  3.39382  3.50174  4.55528  3.62780  0.68858  3.78012  3.62986  3.03247  3.31042  3.51987  5.48103  4.43903    140 P - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    133   2.60256  4.60991  3.08123  2.59418  3.90705  3.39886  3.69738  3.25085  2.27951  2.91739  3.78849  3.05676  3.84470  2.63540  2.79735  2.69573  1.94572  2.76699  5.21418  3.93668    141 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    134   2.16968  3.47307  3.59233  3.22260  4.15866  2.47411  4.19438  3.56363  3.18625  3.27458  4.10858  3.32406  3.66022  3.48496  3.48055  1.23700  2.65371  3.05043  5.52336  4.31592    142 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    135   3.07859  5.21813  0.80740  2.38838  4.60638  3.27362  4.00471  4.21341  3.10456  3.80732  4.78755  2.94873  3.93224  3.24424  3.63163  3.03196  3.41903  3.84400  5.75900  4.46621    143 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    136   2.87283  4.39315  4.23821  3.90420  3.61058  3.80809  4.69198  2.04849  3.77322  2.28363  3.56364  4.08078  4.36427  4.12727  3.97777  3.31702  3.23254  0.92773  5.40873  4.14528    144 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    137   2.50102  4.23694  3.76525  3.33965  3.72246  3.37067  4.24809  2.46042  3.23911  2.55924  3.64161  3.56053  3.97799  3.58142  3.52035  2.77764  1.69802  1.75863  5.30971  4.08018    145 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    138   3.09498  4.49149  4.45102  4.07022  3.43002  4.15408  4.78347  0.98199  3.89992  1.99977  3.35310  4.30411  4.57779  4.24002  4.08717  3.65761  3.39284  1.85079  5.33749  4.08258    146 i - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    139   3.02382  5.15051  2.52384  0.91441  4.50717  3.32764  3.92196  3.97736  2.81286  3.58149  4.55225  2.98104  3.93620  3.13613  3.22992  2.99812  3.32879  3.65289  5.66334  4.38601    147 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    140   2.45786  4.30296  3.50186  3.25812  4.04222  3.13941  4.26905  3.17937  3.20271  3.03994  4.08552  3.45408  3.84975  3.59352  3.45722  2.66008  1.04037  2.86556  5.47283  4.25897    148 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    141   3.08695  4.88934  3.20791  2.97643  3.34377  3.51816  0.98092  3.80251  2.81733  3.28606  4.33566  3.38232  4.07539  3.34383  3.07797  3.15699  3.39324  3.53609  4.80769  3.29239    149 h - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    142   2.99214  5.06805  3.26268  2.74531  4.47846  3.57206  3.65342  3.86981  1.12103  3.36156  4.25702  3.16311  3.99796  2.80635  2.11223  3.00404  3.19554  3.55761  5.42835  4.23089    150 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    143   3.02382  5.15051  2.52384  0.91441  4.50717  3.32764  3.92196  3.97736  2.81286  3.58149  4.55225  2.98104  3.93620  3.13613  3.22992  2.99812  3.32879  3.65289  5.66334  4.38601    151 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    144   2.49167  5.21869  2.13891  1.38935  4.54510  3.23855  3.71342  3.98470  2.64038  3.55288  4.39217  2.73628  3.81159  2.87379  3.17028  2.74234  3.08340  3.59770  5.74876  4.31122    152 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    145   2.67924  5.36825  1.81597  1.42545  4.67130  3.22067  3.71949  4.14895  2.68617  3.67868  4.51726  2.69278  3.81366  2.87890  3.25116  2.76699  3.13943  3.73938  5.85528  4.37934    153 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    146   3.24708  4.60677  4.69416  4.13988  3.08947  4.47063  4.76500  1.92492  3.96672  0.95356  2.71915  4.43331  4.67883  4.15873  4.13317  3.81764  3.47493  2.15974  5.15578  4.04247    154 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02889  3.95434  4.67668  0.61958  0.77255  0.50828  0.92013
+    147   2.69781  4.29649  3.84369  3.29786  3.44437  3.73086  4.15124  2.24231  3.19336  2.10104  3.11890  3.63278  4.14347  3.51043  3.49251  3.03876  2.03846  1.78833  5.07714  3.86271    155 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.18495  3.95434  1.89921  0.61958  0.77255  0.50828  0.92013
+    148   1.44115  4.10304  3.22225  2.99375  4.15355  2.08176  4.10711  3.47540  3.09081  3.24183  4.11431  3.18864  3.61518  3.39097  3.39593  2.35434  2.65737  2.99565  5.50492  4.29375    156 a - - -
+          2.68608  4.42226  2.77520  2.73124  3.46354  2.40513  3.72495  3.29355  2.67741  2.69355  4.24690  2.90347  2.73740  3.18147  2.89801  2.37887  2.77520  2.98519  4.58477  3.61504
+          0.08120  2.55114        *  0.46726  0.98542  0.00000        *
+//
index d9a201a..4ea119c 100755 (executable)
    <mapID target="alwCalc" url="html/menus/alwcalculate.html"/>
    
    <mapID target="wsMenu" url="html/menus/wsmenu.html"/>
+   <mapID target="alwHmmer" url="html/menus/alwhmmer.html"/>
    <mapID target="popMenu" url="html/menus/popupMenu.html"/>
    <mapID target="popMenuAddref" url="html/menus/popupMenu.html#addrefannot"/>
    <mapID target="annotPanelMenu" url="html/menus/alwannotationpanel.html"/>
index b218b88..ca86625 100755 (executable)
                                <tocitem text="Colour Menu" target="alwColour" />
                                <tocitem text="Calculate Menu" target="alwCalc" />
                                <tocitem text="Web Service Menu" target="wsMenu" />
+                               <tocitem text="HMMER Menu" target="alwHmmer" />
                                <tocitem text="Annotation Panel Menu" target="annotPanelMenu" />
                                <tocitem text="Popup Menu" target="popMenu" />
                        </tocitem>
index 50f864b..5bca358 100755 (executable)
       sequence alignments and EPS files.
     </li>
     <li>The <a href="#editing"><strong>&quot;Editing&quot;</strong>
-        Preferences</a> tab contains settings affecting the export of
-      sequence alignments and EPS files.
+        Preferences</a> tab contains settings affecting the behaviour of alignments as you edit them.
+    </li>
+    <li>The <a href="#hmmer"><strong>&quot;HMMER&quot;</strong>
+        Preferences</a> tab allows you to configure locally installed HMMER tools.
     </li>
     <li>The <a href="dassettings.html"><strong>&quot;DAS
           Settings&quot;</strong> Preferences</a> tab allows you to select which DAS
     <em>Sort with New Tree</em> - When selected, any trees calculated or
     loaded onto the alignment will automatically sort the alignment.
   </p>
-  <p>&nbsp;</p>
-  <p>&nbsp;</p>
+  <p>
+    <a name="hmmer"><strong>&quot;HMMER&quot; Preferences tab</strong></a>
+  </p>
+  <p>If you have installed HMMER tools (available from <a href="http://hmmerorg">hmmer.org</a>),
+  then you should specify on this screen the location of the installation (the path to the folder 
+  containing binary executable programs). Double-click in the input field to open a file browser.</p>
+  <p>When this path is configured, the <a href="../menus/alwhmmer.html">HMMER menu</a> will be
+  enabled in the Alignment window.</p>
 </body>
 </html>
diff --git a/help/html/menus/alwhmmer.html b/help/html/menus/alwhmmer.html
new file mode 100644 (file)
index 0000000..ce23c4b
--- /dev/null
@@ -0,0 +1,87 @@
+<html>
+<!--
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ -->
+<head>
+</head>
+<body>
+<p>
+  <strong>HMMER Menu</strong>
+</p>
+<p>This menu is available if hmmbuild tools have been installed and configured in the 
+<a href="../features/preferences.html#hmmer">HMMER Preferences</a> panel.
+  <br><br>
+  
+  <strong>hmmbuild</strong>
+  <br><br>Run hmmbuild to create a Hidden Markov Model profile of your sequence alignment or sub-groups.
+  <br><br>The consensus sequence for the computed profile is inserted as the first sequence of
+  the alignment (or group) for which hmmbuild is run.
+  <br>Jalview also computes and displays an annotation below the alignment, showing
+  the information content of each column.
+  <br>This is calculated as the sum over residue symbols of
+  <pre>
+    match emission probability * log(match emission probability / background frequency) / log(2)
+  </pre>
+  where the background frequencies are taken from (tbc: where? not https://www.ebi.ac.uk/uniprot/TrEMBLstats)
+  <ul>
+  <li>Edit settings and run...
+  <br><br>Choose whether to run hmmbuild for the whole alignment, or all or selected groups, or both 
+  (default is the alignment).
+  <br>Optionally enter a name to give the HMM profile consensus sequence
+  (default is "Alignment" or group name, with "_HMM" appended).
+  <br>Use Reference Annotation: select this option if your alignment has an RF reference annotation,
+  and you wish to constrain the HMM profile to it (hmmbuild option '--hand').
+  <br><br></li>
+  <li>hmmbuild with default settings
+  <br><br>Runs hmmbuild for the whole alignment.</li>
+  </ul>
+  
+  <strong>hmmalign</strong> and <strong>hmmsearch</strong> require an HMM consensus sequence to be selected first.
+  <br><em>To do this, right-click on the name of an HMM sequence added by hmmbuild, and 'Select HMM'.
+  The alignment will be with respect to the HMM profile for the consensus sequence.</em>
+  <br><br>
+  <strong>hmmalign</strong>
+  <br><br>Run hmmalign to align selected sequences (or the whole alignment) to a selected HMM profile.
+  <ul>
+  <li>Edit settings and run...
+  <br><br>Choose whether to 'trim non-matching termini' - hmmalign option '--trim'.
+  <br><br></li>
+  <li>hmmalign with default settings</li>
+  </ul>
+  <strong>hmmsearch</strong>
+  <br><br>Run hmmsearch to use an HMM profile as input to search a sequence database.
+  <ul>
+  <li>Edit settings and run...
+  <ul>
+  <li>tbc: choose database</li>
+  <li>tbc: automatically align</li>
+  <li>tbc: return accessions</li>
+  <li>tbc: number of results</li>
+  <li>tbc: sequence eValue cutoff</li>
+  <li>tbc: domains eValue cutoff</li>
+  </ul>
+  </li>
+  <br><li>hmmsearch with default settings</li>
+  <br><li>Add database
+  <br>Browse to select a local sequence data file to be searched</li>
+  </ul>
+<br>
+</body>
+</html>
index 08a416c..db3dbf8 100644 (file)
@@ -11,6 +11,7 @@ action.paste = Paste
 action.show_html_source = Show HTML Source
 action.print = Print...
 action.web_service = Web Service
+action.hmmer = HMMER
 action.cancel_job = Cancel Job
 action.start_job = Start Job
 action.revert = Revert
@@ -203,6 +204,8 @@ label.colourScheme_purine/pyrimidine = Purine/Pyrimidine
 label.colourScheme_nucleotide = Nucleotide
 label.colourScheme_t-coffee_scores = T-Coffee Scores
 label.colourScheme_rna_helices = By RNA Helices
+label.colourScheme_hmmer-uniprot = HMMER profile v global background
+label.colourScheme_hmmer-alignment = HMMER profile v alignment background
 label.blc = BLC
 label.fasta = Fasta
 label.msf = MSF
@@ -815,8 +818,8 @@ label.fetch_retrieve_from_all_sources = Retrieve from all {0} sources in {1}<br>
 label.feature_settings_click_drag = Drag up or down to change render order.<br/>Double click to select columns containing feature.
 label.transparency_tip = Adjust transparency to 'see through' feature colours.
 label.opt_and_params_further_details = see further details by right-clicking
-label.opt_and_params_show_brief_desc_image_link = <html>Click to show brief description<br><img src="{0}"/> Right click for further information.</html> 
-label.opt_and_params_show_brief_desc = <html>Click to show brief description<br></html>
+label.opt_and_params_show_brief_desc_image_link = Click to show brief description<br><img src="{0}"/> Right click for further information. 
+label.opt_and_params_show_brief_desc = Click to show brief description<br>
 label.adjusts_width_generated_eps_png = <html>Adjusts the width of the generated EPS or PNG file to ensure even the longest sequence ID or annotation label is displayed</html>
 label.manually_specify_width_left_column = <html>Manually specify the width of the left hand column where sequence IDs and annotation labels will be rendered in exported alignment figures. This setting will be ignored if 'Automatically set ID width' is set</html>
 label.job_created_when_checked = <html>When checked, a job is created for every sequence in the current selection.</html>
@@ -878,7 +881,6 @@ label.error_unsupported_owwner_user_colour_scheme = Unsupported owner for User C
 label.save_alignment_to_file = Save Alignment to file
 label.save_features_to_file = Save Features to File
 label.save_annotation_to_file = Save Annotation to File
-label.no_features_on_alignment = No features found on alignment
 label.save_pdb_file = Save PDB File
 label.save_text_to_file = Save Text to File
 label.save_state = Save State
@@ -957,7 +959,6 @@ label.groovy_support_failed = Jalview Groovy Support Failed
 label.couldnt_create_groovy_shell = Couldn't create the groovy Shell. Check the error log for the details of what went wrong.
 error.unsupported_version_calcIdparam = Unsupported Version for calcIdparam {0}
 error.implementation_error_cant_reorder_tree = Implementation Error: Can't reorder this tree. Not DefaultMutableTreeNode.
-error.invalid_value_for_option = Invalid value {0} for option {1}
 error.implementation_error_cannot_import_vamsas_doc = Implementation Error - cannot import existing vamsas document into an existing session, Yet!
 label.vamsas_doc_couldnt_be_opened_as_new_session = VAMSAS Document could not be opened as a new session - please choose another
 error.implementation_error_vamsas_operation_not_init = Impementation error! Vamsas Operations when client not initialised and connected
@@ -1143,6 +1144,9 @@ status.loading_cached_pdb_entries = Loading Cached PDB Entries
 status.searching_for_pdb_structures = Searching for PDB Structures
 status.opening_file_for = opening file for
 status.colouring_chimera = Colouring Chimera
+status.running_hmmbuild = Building Hidden Markov Model
+status.running_hmmalign = Creating alignment with Hidden Markov Model
+status.running_hmmsearch = Searching for matching sequences
 label.font_doesnt_have_letters_defined = Font doesn't have letters defined\nso cannot be used\nwith alignment data
 label.font_too_small = Font size is too small
 label.error_loading_file_params = Error loading file {0}
@@ -1362,3 +1366,57 @@ label.most_bound_molecules = Most Bound Molecules
 label.most_polymer_residues = Most Polymer Residues
 label.cached_structures = Cached Structures
 label.free_text_search = Free Text Search
+label.hmmalign = hmmalign
+label.use_hmm = HMM profile to use
+label.hmmbuild = hmmbuild
+label.hmmsearch = hmmsearch
+label.installation = Installation
+label.hmmer_location = HMMER Binaries Installation Location
+label.cygwin_location = Cygwin Binaries Installation Location (Windows)
+label.information_annotation = Information Annotation
+label.ignore_below_background_frequency = Ignore Below Background Frequency
+label.information_description = Information content, measured in bits
+warn.no_hmm = No Hidden Markov model found.\nRun hmmbuild or load an HMM file first.
+label.no_sequences_found = No matching sequences, or an error occurred.
+label.hmmer = HMMER
+label.trim_termini = Trim Non-Matching Termini
+label.trim_termini_desc = If true, non-matching regions on either end of the resulting alignment are removed.
+label.no_of_sequences = Number of sequences returned
+label.reporting_cutoff = Reporting Cut-off
+label.freq_alignment = Use alignment background frequencies
+label.freq_uniprot = Use Uniprot background frequencies
+label.hmmalign_options = hmmalign options
+label.hmmsearch_options = hmmsearch options
+label.executable_not_found = The ''{0}'' executable file was not found
+warn.command_failed = {0} failed
+label.invalid_folder = Invalid Folder
+label.number_of_results = Number of Results to Return
+label.auto_align_seqs = Automatically Align Fetched Sequences
+label.use_accessions = Return Accessions
+label.seq_evalue = Sequence E-value Cut-off
+label.seq_score = Sequence Score Threshold
+label.dom_evalue = Domain E-value Cut-off
+label.dom_score = Domain Score Threshold
+label.number_of_results_desc = The maximum number of hmmsearch results to display
+label.auto_align_seqs_desc = If true, all fetched sequences will be aligned to the hidden Markov model with which the search was performed
+label.use_accessions_desc = If true, the accession number of each sequence is returned, rather than that sequence's name
+label.seq_e_value_desc = The E-value cutoff for returned sequences (hmmsearch -E)
+label.seq_score_desc = The score threshold for returned sequences (hmmsearch -T)
+label.dom_e_value_desc = The E-value cutoff for returned domains (hmmsearch --domE)
+label.dom_score_desc = The score threshold for returned domains (hmmsearch --domT)
+label.add_database = Add Database
+label.this_alignment = This alignment
+warn.invalid_format = This is not a valid database file format. The current supported formats are Fasta, Stockholm and Pfam.
+label.database_for_hmmsearch = The database hmmsearch will search through
+label.use_reference = Use Reference Annotation
+label.use_reference_desc = If true, hmmbuild will keep all columns defined as a reference position by the reference annotation
+label.hmm_name = Alignment HMM Name
+label.hmm_name_desc = The name given to the HMM for the alignment
+warn.no_reference_annotation = No reference annotation found
+label.hmmbuild_for = Build HMM for
+label.hmmbuild_for_desc = Build an HMM for the selected sets of sequences
+label.alignment = Alignment
+label.groups_and_alignment = All groups and alignment
+label.groups = All groups
+label.selected_group = Selected group
+label.use_info_for_height = Use Information Content as Letter Height
index 17c6112..0144522 100644 (file)
@@ -804,7 +804,6 @@ label.error_unsupported_owwner_user_colour_scheme = Propietario no soportado par
 label.save_alignment_to_file = Guardar Alineamiento en fichero
 label.save_features_to_file = Guardar Características en un fichero
 label.save_annotation_to_file = Guardar Anotación en un fichero
-label.no_features_on_alignment = No se han encontrado características en el alineamiento
 label.save_pdb_file = Guardar fichero PDB 
 label.save_text_to_file = Guardar Texto en un fichero
 label.save_state = Guardar estado
@@ -883,7 +882,6 @@ label.groovy_support_failed = El soporte Groovy de Jalview ha fallado
 label.couldnt_create_groovy_shell = No es posible crear el shell de Groovy. Compruebe el fichero de log para conocer los detalles.
 error.unsupported_version_calcIdparam = Versión no soportada de {0}
 error.implementation_error_cant_reorder_tree = Error de implementación: no es posible reordenar este Ã¡rbol. No DefaultMutableTreeNode.
-error.invalid_value_for_option = Valor no válido de {0} para la opción {1}
 error.implementation_error_cannot_import_vamsas_doc = Error de implementación - todavía no es posible importar el documento VAMSAS existente en una sesión existente.
 label.vamsas_doc_couldnt_be_opened_as_new_session = El documento VAMSAS no ha podido abrirse como una nueva sesión. Por favor, escoja otra.
 error.implementation_error_vamsas_operation_not_init = Â¡Error de implementación! Operaciones VAMSAS cuando el cliente no estaba inicializado ni conectado
index 48824e7..d5cd5bc 100755 (executable)
                                                                        </xs:attribute>
                                                                </xs:complexType>
                                                        </xs:element>
+                                                       <xs:element name="hmmerProfile" minOccurs="0" type="xs:string">
+                                                               <xs:annotation>
+                                                                       <xs:documentation>name of the project jar entry that holds the HMM file with the profile for the sequence</xs:documentation>
+                                                               </xs:annotation>
+                                                       </xs:element>
                                                </xs:sequence>
                                                <xs:attribute name="colour" type="xs:int" use="optional" />
                                                <xs:attribute name="start" type="xs:int" use="required" />
index e4f2dfa..11c8f72 100755 (executable)
@@ -24,6 +24,7 @@ import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.Profile;
 import jalview.datamodel.ProfileI;
 import jalview.datamodel.Profiles;
@@ -32,6 +33,7 @@ import jalview.datamodel.ResidueCount;
 import jalview.datamodel.ResidueCount.SymbolCounts;
 import jalview.datamodel.SequenceI;
 import jalview.ext.android.SparseIntArray;
+import jalview.schemes.ResidueProperties;
 import jalview.util.Comparison;
 import jalview.util.Format;
 import jalview.util.MappingUtils;
@@ -48,25 +50,12 @@ import java.util.List;
  * This class is used extensively in calculating alignment colourschemes that
  * depend on the amount of conservation in each alignment column.
  * 
- * @author $author$
- * @version $Revision$
  */
 public class AAFrequency
 {
-  public static final String PROFILE = "P";
-
-  /*
-   * Quick look-up of String value of char 'A' to 'Z'
-   */
-  private static final String[] CHARS = new String['Z' - 'A' + 1];
+  private static final double LOG2 = Math.log(2);
 
-  static
-  {
-    for (char c = 'A'; c <= 'Z'; c++)
-    {
-      CHARS[c - 'A'] = String.valueOf(c);
-    }
-  }
+  public static final String PROFILE = "P";
 
   public static final ProfilesI calculate(List<SequenceI> list, int start,
           int end)
@@ -192,6 +181,52 @@ public class AAFrequency
   }
 
   /**
+   * Returns the full set of profiles for a hidden Markov model. The underlying
+   * data is the raw probabilities of a residue being emitted at each node,
+   * however the profiles returned by this function contain the percentage
+   * chance of a residue emission.
+   * 
+   * @param hmm
+   * @param width
+   *          The width of the Profile array (Profiles) to be returned.
+   * @param start
+   *          The alignment column on which the first profile is based.
+   * @param end
+   *          The alignment column on which the last profile is based.
+   * @param removeBelowBackground
+   *          if true, symbols with a match emission probability less than
+   *          background frequency are ignored
+   * @return
+   */
+  public static ProfilesI calculateHMMProfiles(final HiddenMarkovModel hmm,
+          int width, int start, int end, boolean removeBelowBackground,
+          boolean infoLetterHeight)
+  {
+    ProfileI[] result = new ProfileI[width];
+    char[] symbols = hmm.getSymbols().toCharArray();
+    int symbolCount = symbols.length;
+    for (int column = start; column < end; column++)
+    {
+      ResidueCount counts = new ResidueCount();
+      for (char symbol : symbols)
+      {
+        int value = getAnalogueCount(hmm, column, symbol,
+                removeBelowBackground, infoLetterHeight);
+        counts.put(symbol, value);
+      }
+      int maxCount = counts.getModalCount();
+      String maxResidue = counts.getResiduesForCount(maxCount);
+      int gapCount = counts.getGapCount();
+      ProfileI profile = new Profile(symbolCount, gapCount, maxCount,
+              maxResidue);
+      profile.setCounts(counts);
+
+      result[column] = profile;
+    }
+    return new Profiles(result);
+  }
+
+  /**
    * Make an estimate of the profile size we are going to compute i.e. how many
    * different characters may be present in it. Overestimating has a cost of
    * using more memory than necessary. Underestimating has a cost of needing to
@@ -289,9 +324,80 @@ public class AAFrequency
   }
 
   /**
-   * Derive the gap count annotation row.
+   * Derive the information annotations to be added to the alignment for
+   * display. This does not recompute the raw data, but may be called on a
+   * change in display options, such as 'ignore below background frequency',
+   * which may in turn result in a change in the derived values.
    * 
-   * @param gaprow
+   * @param information
+   *          the annotation row to add annotations to
+   * @param profiles
+   *          the source information data
+   * @param startCol
+   *          start column (inclusive)
+   * @param endCol
+   *          end column (exclusive)
+   * @param ignoreGaps
+   *          if true, normalise residue percentages
+   * @param showSequenceLogo
+   *          if true include all information symbols, else just show modal
+   *          residue
+   */
+  public static float completeInformation(AlignmentAnnotation information,
+          ProfilesI profiles, int startCol, int endCol)
+  {
+    // long now = System.currentTimeMillis();
+    if (information == null || information.annotations == null)
+    {
+      /*
+       * called with a bad alignment annotation row 
+       * wait for it to be initialised properly
+       */
+      return 0;
+    }
+
+    float max = 0f;
+    SequenceI hmmSeq = information.sequenceRef;
+
+    int seqLength = hmmSeq.getLength();
+    if (information.annotations.length < seqLength)
+    {
+      return 0;
+    }
+
+    HiddenMarkovModel hmm = hmmSeq.getHMM();
+
+    for (int column = startCol; column < endCol; column++)
+    {
+      if (column >= seqLength)
+      {
+        // hmm consensus sequence is shorter than the alignment
+        break;
+      }
+      
+      float value = hmm.getInformationContent(column);
+      boolean isNaN = Float.isNaN(value);
+      if (!isNaN)
+      {
+        max = Math.max(max, value);
+      }
+
+      String description = isNaN ? null
+              : String.format("%.4f bits", value);
+      information.annotations[column] = new Annotation(
+              Character.toString(
+                      Character.toUpperCase(hmmSeq.getCharAt(column))),
+              description, ' ', value);
+    }
+
+    information.graphMax = max;
+    return max;
+  }
+
+  /**
+   * Derive the occupancy count annotation
+   * 
+   * @param occupancy
    *          the annotation row to add annotations to
    * @param profiles
    *          the source consensus data
@@ -300,11 +406,11 @@ public class AAFrequency
    * @param endCol
    *          end column (exclusive)
    */
-  public static void completeGapAnnot(AlignmentAnnotation gaprow,
+  public static void completeOccupancyAnnot(AlignmentAnnotation occupancy,
           ProfilesI profiles, int startCol, int endCol, long nseq)
   {
-    if (gaprow == null || gaprow.annotations == null
-            || gaprow.annotations.length < endCol)
+    if (occupancy == null || occupancy.annotations == null
+            || occupancy.annotations.length < endCol)
     {
       /*
        * called with a bad alignment annotation row 
@@ -313,8 +419,8 @@ public class AAFrequency
       return;
     }
     // always set ranges again
-    gaprow.graphMax = nseq;
-    gaprow.graphMin = 0;
+    occupancy.graphMax = nseq;
+    occupancy.graphMin = 0;
     double scale = 0.8 / nseq;
     for (int i = startCol; i < endCol; i++)
     {
@@ -325,7 +431,7 @@ public class AAFrequency
          * happens if sequences calculated over were 
          * shorter than alignment width
          */
-        gaprow.annotations[i] = null;
+        occupancy.annotations[i] = null;
         return;
       }
 
@@ -333,7 +439,8 @@ public class AAFrequency
 
       String description = "" + gapped;
 
-      gaprow.annotations[i] = new Annotation("", description, '\0', gapped,
+      occupancy.annotations[i] = new Annotation("", description, '\0',
+              gapped,
               jalview.util.ColorUtils.bleachColour(Color.DARK_GRAY,
                       (float) scale * gapped));
     }
@@ -449,6 +556,7 @@ public class AAFrequency
     return result;
   }
 
+
   /**
    * Extract a sorted extract of cDNA codon profile data. The returned array
    * contains
@@ -531,7 +639,7 @@ public class AAFrequency
     for (int col = 0; col < cols; col++)
     {
       // todo would prefer a Java bean for consensus data
-      Hashtable<String, int[]> columnHash = new Hashtable<String, int[]>();
+      Hashtable<String, int[]> columnHash = new Hashtable<>();
       // #seqs, #ungapped seqs, counts indexed by (codon encoded + 1)
       int[] codonCounts = new int[66];
       codonCounts[0] = alignment.getSequences().size();
@@ -718,4 +826,118 @@ public class AAFrequency
     }
     return scale;
   }
+
+  /**
+   * Returns the sorted HMM profile for the given column of the alignment. The
+   * returned array contains
+   * 
+   * <pre>
+   *    [profileType=0, numberOfValues, 100, charValue1, percentage1, charValue2, percentage2, ...]
+   * in descending order of percentage value
+   * </pre>
+   * 
+   * @param hmm
+   * @param column
+   * @param removeBelowBackground
+   *          if true, ignores residues with probability less than their
+   *          background frequency
+   * @param infoHeight
+   *          if true, uses the log ratio 'information' measure to scale the
+   *          value
+   * @return
+   */
+  public static int[] extractHMMProfile(HiddenMarkovModel hmm, int column,
+          boolean removeBelowBackground, boolean infoHeight)
+  {
+    if (hmm == null)
+    {
+      return null;
+    }
+    String alphabet = hmm.getSymbols();
+    int size = alphabet.length();
+    char symbols[] = new char[size];
+    int values[] = new int[size];
+    int totalCount = 0;
+
+    for (int i = 0; i < size; i++)
+    {
+      char symbol = alphabet.charAt(i);
+      symbols[i] = symbol;
+      int value = getAnalogueCount(hmm, column, symbol,
+              removeBelowBackground, infoHeight);
+      values[i] = value;
+      totalCount += value;
+    }
+
+    /*
+     * sort symbols by increasing emission probability
+     */
+    QuickSort.sort(values, symbols);
+
+    int[] profile = new int[3 + size * 2];
+
+    profile[0] = AlignmentAnnotation.SEQUENCE_PROFILE;
+    profile[1] = size;
+    profile[2] = 100;
+
+    /*
+     * order symbol/count profile by decreasing emission probability
+     */
+    if (totalCount != 0)
+    {
+      int arrayPos = 3;
+      for (int k = size - 1; k >= 0; k--)
+      {
+        Float percentage;
+        int value = values[k];
+        if (removeBelowBackground)
+        {
+          percentage = ((float) value) / totalCount * 100f;
+        }
+        else
+        {
+          percentage = value / 100f;
+        }
+        int intPercent = Math.round(percentage);
+        profile[arrayPos] = symbols[k];
+        profile[arrayPos + 1] = intPercent;
+        arrayPos += 2;
+      }
+    }
+    return profile;
+  }
+
+  /**
+   * Converts the emission probability of a residue at a column in the alignment
+   * to a 'count', suitable for rendering as an annotation value
+   * 
+   * @param hmm
+   * @param column
+   * @param symbol
+   * @param removeBelowBackground
+   *          if true, returns 0 for any symbol with a match emission
+   *          probability less than the background frequency
+   * @infoHeight if true, uses the log ratio 'information content' to scale the
+   *             value
+   * @return
+   */
+  static int getAnalogueCount(HiddenMarkovModel hmm, int column,
+          char symbol, boolean removeBelowBackground, boolean infoHeight)
+  {
+    double value = hmm.getMatchEmissionProbability(column, symbol);
+    double freq = ResidueProperties.backgroundFrequencies
+            .get(hmm.getAlphabetType()).get(symbol);
+    if (value < freq && removeBelowBackground)
+    {
+      return 0;
+    }
+
+    if (infoHeight)
+    {
+      value = value * (Math.log(value / freq) / LOG2);
+    }
+
+    value = value * 10000d;
+    return Math.round((float) value);
+  }
 }
index fabd0c6..921ab2a 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.analysis;
 
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
@@ -35,7 +36,7 @@ public class SeqsetUtils
 
   /**
    * Store essential properties of a sequence in a hashtable for later recovery
-   * Keys are Name, Start, End, SeqFeatures, PdbId
+   * Keys are Name, Start, End, SeqFeatures, PdbId, HMM
    * 
    * @param seq
    *          SequenceI
@@ -52,7 +53,7 @@ public class SeqsetUtils
       sqinfo.put("Description", seq.getDescription());
     }
 
-    Vector<SequenceFeature> sfeat = new Vector<SequenceFeature>();
+    Vector<SequenceFeature> sfeat = new Vector<>();
     List<SequenceFeature> sfs = seq.getFeatures().getAllFeatures();
     sfeat.addAll(sfs);
 
@@ -69,6 +70,10 @@ public class SeqsetUtils
               (seq.getDatasetSequence() != null) ? seq.getDatasetSequence()
                       : new Sequence("THISISAPLACEHOLDER", ""));
     }
+    if (seq.hasHMMProfile())
+    {
+      sqinfo.put("HMM", seq.getHMM());
+    }
     return sqinfo;
   }
 
@@ -97,6 +102,7 @@ public class SeqsetUtils
     Vector<PDBEntry> pdbid = (Vector<PDBEntry>) sqinfo.get("PdbId");
     String description = (String) sqinfo.get("Description");
     Sequence seqds = (Sequence) sqinfo.get("datasetSequence");
+    HiddenMarkovModel hmm = (HiddenMarkovModel) sqinfo.get("HMM");
     if (oldname == null)
     {
       namePresent = false;
@@ -135,6 +141,10 @@ public class SeqsetUtils
       sq.setDatasetSequence(seqds);
     }
 
+    if (hmm != null)
+    {
+      sq.setHMM(new HiddenMarkovModel(hmm, sq));
+    }
     return namePresent;
   }
 
index 85157c4..1387cba 100644 (file)
@@ -39,8 +39,8 @@ public interface AlignCalcWorkerI extends Runnable
 
   /**
    * Updates the display of calculated annotation values (does not recalculate
-   * the values). This allows ÃŸquick redraw of annotations when display settings
-   * are changed.
+   * the values). This allows a quick redraw of annotations when display
+   * settings are changed.
    */
   void updateAnnotation();
 
index 931eba6..6b3cbe8 100644 (file)
@@ -54,7 +54,7 @@ public interface AlignViewportI extends ViewStyleI
    * 
    * @return
    */
-  public ViewportRanges getRanges();
+  ViewportRanges getRanges();
 
   /**
    * calculate the height for visible annotation, revalidating bounds where
@@ -62,7 +62,7 @@ public interface AlignViewportI extends ViewStyleI
    * 
    * @return total height of annotation
    */
-  public int calcPanelHeight();
+  int calcPanelHeight();
 
   /**
    * Answers true if the viewport has at least one column selected
@@ -86,6 +86,12 @@ public interface AlignViewportI extends ViewStyleI
 
   boolean isNormaliseSequenceLogo();
 
+  boolean isShowInformationHistogram();
+
+  boolean isShowHMMSequenceLogo();
+
+  boolean isNormaliseHMMSequenceLogo();
+
   ColourSchemeI getGlobalColourScheme();
 
   /**
@@ -100,7 +106,7 @@ public interface AlignViewportI extends ViewStyleI
 
   ColumnSelection getColumnSelection();
 
-  ProfilesI getSequenceConsensusHash();
+  ProfilesI getConsensusProfiles();
 
   /**
    * Get consensus data table for the cDNA complement of this alignment (if any)
@@ -113,6 +119,8 @@ public interface AlignViewportI extends ViewStyleI
 
   boolean isIgnoreGapsConsensus();
 
+  boolean isIgnoreBelowBackground();
+
   boolean isCalculationInProgress(AlignmentAnnotation alignmentAnnotation);
 
   AlignmentAnnotation getAlignmentQualityAnnot();
@@ -131,7 +139,7 @@ public interface AlignViewportI extends ViewStyleI
    * 
    * @return
    */
-  AlignmentAnnotation getAlignmentGapAnnotation();
+  AlignmentAnnotation getOccupancyAnnotation();
 
   /**
    * get the container for cDNA complement consensus annotation
@@ -170,7 +178,7 @@ public interface AlignViewportI extends ViewStyleI
    * 
    * @param hconsensus
    */
-  void setSequenceConsensusHash(ProfilesI hconsensus);
+  void setConsensusProfiles(ProfilesI hconsensus);
 
   /**
    * Set the cDNA complement consensus for the viewport
@@ -380,14 +388,14 @@ public interface AlignViewportI extends ViewStyleI
    * 
    * @return a copy of this view's current display settings
    */
-  public ViewStyleI getViewStyle();
+  ViewStyleI getViewStyle();
 
   /**
    * update the view's display settings with the given style set
    * 
    * @param settingsForView
    */
-  public void setViewStyle(ViewStyleI settingsForView);
+  void setViewStyle(ViewStyleI settingsForView);
 
   /**
    * Returns a viewport which holds the cDna for this (protein), or vice versa,
@@ -431,7 +439,7 @@ public interface AlignViewportI extends ViewStyleI
    */
   void setFollowHighlight(boolean b);
 
-  public void applyFeaturesStyle(FeatureSettingsModelI featureSettings);
+  void applyFeaturesStyle(FeatureSettingsModelI featureSettings);
 
   /**
    * check if current selection group is defined on the view, or is simply a
@@ -487,7 +495,21 @@ public interface AlignViewportI extends ViewStyleI
   @Override
   void setProteinFontAsCdna(boolean b);
 
-  public abstract TreeModel getCurrentTree();
+  void setHmmProfiles(ProfilesI info);
+
+  ProfilesI getHmmProfiles();
+
+  /**
+   * Registers and starts a worker thread to calculate Information Content
+   * annotation, if it is not already registered
+   * 
+   * @param ap
+   */
+  void initInformationWorker(AlignmentViewPanel ap);
+
+  boolean isInfoLetterHeight();
+
+  abstract TreeModel getCurrentTree();
 
-  public abstract void setCurrentTree(TreeModel tree);
+  abstract void setCurrentTree(TreeModel tree);
 }
index 5ad212e..28aabe1 100644 (file)
@@ -234,6 +234,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
             alignPanel);
     viewport.updateConservation(alignPanel);
     viewport.updateConsensus(alignPanel);
+    viewport.initInformationWorker(alignPanel);
 
     displayNonconservedMenuItem.setState(viewport.getShowUnconserved());
     followMouseOverFlag.setState(viewport.isFollowHighlight());
index 262948d..753e972 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
  * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
  * 
  * This file is part of Jalview.
  * 
@@ -25,14 +25,11 @@ import jalview.api.FeatureSettingsModelI;
 import jalview.bin.JalviewLite;
 import jalview.commands.CommandI;
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.Annotation;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SearchResultsI;
-import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceGroup;
-import jalview.datamodel.SequenceI;
 import jalview.renderer.ResidueShader;
 import jalview.schemes.ColourSchemeProperty;
 import jalview.schemes.UserColourScheme;
@@ -59,6 +56,12 @@ public class AlignViewport extends AlignmentViewport
 
   private AnnotationColumnChooser annotationColumnSelectionState;
 
+  java.awt.Frame nullFrame;
+
+  protected FeatureSettings featureSettings = null;
+
+  private float heightScale = 1, widthScale = 1;
+
   public AlignViewport(AlignmentI al, JalviewLite applet)
   {
     super(al);
@@ -200,10 +203,11 @@ public class AlignViewport extends AlignmentViewport
       if (colour != null)
       {
         residueShading = new ResidueShader(
-                ColourSchemeProperty.getColourScheme(alignment, colour));
+                ColourSchemeProperty.getColourScheme(getAlignment(),
+                        colour));
         if (residueShading != null)
         {
-          residueShading.setConsensus(hconsensus);
+          residueShading.setConsensus(consensusProfiles);
         }
       }
 
@@ -214,15 +218,8 @@ public class AlignViewport extends AlignmentViewport
       }
     }
     initAutoAnnotation();
-
   }
 
-  java.awt.Frame nullFrame;
-
-  protected FeatureSettings featureSettings = null;
-
-  private float heightScale = 1, widthScale = 1;
-
   /**
    * {@inheritDoc}
    */
@@ -302,17 +299,6 @@ public class AlignViewport extends AlignmentViewport
             .getStructureSelectionManager(applet);
   }
 
-  @Override
-  public boolean isNormaliseSequenceLogo()
-  {
-    return normaliseSequenceLogo;
-  }
-
-  public void setNormaliseSequenceLogo(boolean state)
-  {
-    normaliseSequenceLogo = state;
-  }
-
   /**
    * 
    * @return true if alignment characters should be displayed
index 83d8ade..730434f 100644 (file)
@@ -554,8 +554,8 @@ public class AlignmentPanel extends Panel
     // this is called after loading new annotation onto alignment
     if (alignFrame.getSize().height == 0)
     {
-      System.out.println(
-              "adjustAnnotationHeight frame size zero NEEDS FIXING");
+      // panel not laid out yet?
+      return;
     }
     fontChanged();
     validateAnnotationDimensions(true);
index 1366f31..71dc3da 100755 (executable)
@@ -534,7 +534,7 @@ public class AnnotationLabels extends Panel
                     MessageManager.getString("label.ignore_gaps_consensus"),
                     (aa[selectedRow].groupRef != null)
                             ? aa[selectedRow].groupRef
-                                    .getIgnoreGapsConsensus()
+                                    .isIgnoreGapsConsensus()
                             : ap.av.isIgnoreGapsConsensus());
             final AlignmentAnnotation aaa = aa[selectedRow];
             cbmi.addItemListener(new ItemListener()
index 3bbbe95..e09280f 100755 (executable)
@@ -69,7 +69,7 @@ public class OverviewPanel extends Panel implements Runnable,
 
     od = new OverviewDimensionsShowHidden(av.getRanges(),
             (av.isShowAnnotation()
-                    && av.getSequenceConsensusHash() != null));
+                    && av.getConsensusProfiles() != null));
 
     oviewCanvas = new OverviewCanvas(od, av);
     setLayout(new BorderLayout());
index e07dae6..285c737 100644 (file)
@@ -1498,7 +1498,7 @@ public class SeqPanel extends Panel implements MouseMotionListener,
     }
     // always do this - annotation has own state
     // but defer colourscheme update until hidden sequences are passed in
-    boolean vischange = stretchGroup.recalcConservation(true);
+    boolean vischange = stretchGroup.recalcAnnotations(true);
     // here we rely on stretchGroup == av.getSelection()
     needOverviewUpdate |= vischange && av.isSelectionDefinedGroup()
             && afterDrag;
index 287096d..e66b7ae 100755 (executable)
@@ -175,6 +175,8 @@ public class Jalview
    * 
    * @param args
    *          open <em>filename</em>
+   * @throws InterruptedException
+   * @throws IOException
    */
   public static void main(String[] args)
   {
@@ -184,6 +186,8 @@ public class Jalview
 
   /**
    * @param args
+   * @throws InterruptedException
+   * @throws IOException
    */
   void doMain(String[] args)
   {
@@ -299,7 +303,7 @@ public class Jalview
         {
           System.err.println(
                   "Quaqua LaF not available. Using VAqua(4).");
-          UIManager.setLookAndFeel("org.violetlib.aqua.AquaLookAndFeel");
+          // UIManager.setLookAndFeel("org.violetlib.aqua.AquaLookAndFeel");
         } catch (Throwable e)
         {
           System.err.println(
index 3ba35b6..e3b4c64 100755 (executable)
@@ -291,6 +291,32 @@ public class Alignment implements AlignmentI
   }
 
   /**
+   * Inserts a sequence at a point in the alignment.
+   * 
+   * @param i
+   *          the index of the position the sequence is to be inserted in.
+   */
+  @Override
+  public void insertSequenceAt(int i, SequenceI snew)
+  {
+    synchronized (sequences)
+    {
+      if (sequences.size() > i)
+      {
+        sequences.add(i, snew);
+        return;
+
+      }
+      else
+      {
+        sequences.add(snew);
+        hiddenSequences.adjustHeightSequenceAdded();
+      }
+      return;
+    }
+  }
+
+  /**
    * DOCUMENT ME!
    * 
    * @return DOCUMENT ME!
@@ -1633,7 +1659,7 @@ public class Alignment implements AlignmentI
     annot.hasText = false;
     if (calcId != null)
     {
-      annot.setCalcId(new String(calcId));
+      annot.setCalcId(calcId);
     }
     annot.autoCalculated = autoCalc;
     if (seqRef != null)
@@ -2039,4 +2065,18 @@ public class Alignment implements AlignmentI
     }
   }
 
+  @Override
+  public List<SequenceI> getHmmSequences()
+  {
+    List<SequenceI> result = new ArrayList<>();
+    for (int i = 0; i < sequences.size(); i++)
+    {
+      SequenceI seq = sequences.get(i);
+      if (seq.hasHMMProfile())
+      {
+        result.add(seq);
+      }
+    }
+    return result;
+  }
 }
index 0098d76..0f7883e 100755 (executable)
@@ -94,76 +94,6 @@ public class AlignmentAnnotation
   private long invalidrnastruc = -2;
 
   /**
-   * Updates the _rnasecstr field Determines the positions that base pair and
-   * the positions of helices based on secondary structure from a Stockholm file
-   * 
-   * @param rnaAnnotation
-   */
-  private void _updateRnaSecStr(CharSequence rnaAnnotation)
-  {
-    try
-    {
-      _rnasecstr = Rna.getHelixMap(rnaAnnotation);
-      invalidrnastruc = -1;
-    } catch (WUSSParseException px)
-    {
-      // DEBUG System.out.println(px);
-      invalidrnastruc = px.getProblemPos();
-    }
-    if (invalidrnastruc > -1)
-    {
-      return;
-    }
-
-    if (_rnasecstr != null && _rnasecstr.length > 0)
-    {
-      // show all the RNA secondary structure annotation symbols.
-      isrna = true;
-      showAllColLabels = true;
-      scaleColLabel = true;
-      _markRnaHelices();
-    }
-    // System.out.println("featuregroup " + _rnasecstr[0].getFeatureGroup());
-
-  }
-
-  private void _markRnaHelices()
-  {
-    int mxval = 0;
-    // Figure out number of helices
-    // Length of rnasecstr is the number of pairs of positions that base pair
-    // with each other in the secondary structure
-    for (int x = 0; x < _rnasecstr.length; x++)
-    {
-
-      /*
-       * System.out.println(this.annotation._rnasecstr[x] + " Begin" +
-       * this.annotation._rnasecstr[x].getBegin());
-       */
-      // System.out.println(this.annotation._rnasecstr[x].getFeatureGroup());
-      int val = 0;
-      try
-      {
-        val = Integer.valueOf(_rnasecstr[x].getFeatureGroup());
-        if (mxval < val)
-        {
-          mxval = val;
-        }
-      } catch (NumberFormatException q)
-      {
-      }
-      ;
-
-      annotations[_rnasecstr[x].getBegin()].value = val;
-      annotations[_rnasecstr[x].getEnd()].value = val;
-
-      // annotations[_rnasecstr[x].getBegin()].displayCharacter = "" + val;
-      // annotations[_rnasecstr[x].getEnd()].displayCharacter = "" + val;
-    }
-    setScore(mxval);
-  }
-
-  /**
    * map of positions in the associated annotation
    */
   private Map<Integer, Annotation> sequenceMapping;
@@ -282,6 +212,245 @@ public class AlignmentAnnotation
   }
 
   /**
+   * Copy constructor creates a new independent annotation row with the same
+   * associated sequenceRef
+   * 
+   * @param annotation
+   */
+  public AlignmentAnnotation(AlignmentAnnotation annotation)
+  {
+    setAnnotationId();
+    this.label = new String(annotation.label);
+    if (annotation.description != null)
+    {
+      this.description = new String(annotation.description);
+    }
+    this.graphMin = annotation.graphMin;
+    this.graphMax = annotation.graphMax;
+    this.graph = annotation.graph;
+    this.graphHeight = annotation.graphHeight;
+    this.graphGroup = annotation.graphGroup;
+    this.groupRef = annotation.groupRef;
+    this.editable = annotation.editable;
+    this.autoCalculated = annotation.autoCalculated;
+    this.hasIcons = annotation.hasIcons;
+    this.hasText = annotation.hasText;
+    this.height = annotation.height;
+    this.label = annotation.label;
+    this.padGaps = annotation.padGaps;
+    this.visible = annotation.visible;
+    this.centreColLabels = annotation.centreColLabels;
+    this.scaleColLabel = annotation.scaleColLabel;
+    this.showAllColLabels = annotation.showAllColLabels;
+    this.calcId = annotation.calcId;
+    if (annotation.properties != null)
+    {
+      properties = new HashMap<>();
+      for (Map.Entry<String, String> val : annotation.properties.entrySet())
+      {
+        properties.put(val.getKey(), val.getValue());
+      }
+    }
+    if (this.hasScore = annotation.hasScore)
+    {
+      this.score = annotation.score;
+    }
+    if (annotation.threshold != null)
+    {
+      threshold = new GraphLine(annotation.threshold);
+    }
+    Annotation[] ann = annotation.annotations;
+    if (annotation.annotations != null)
+    {
+      this.annotations = new Annotation[ann.length];
+      for (int i = 0; i < ann.length; i++)
+      {
+        if (ann[i] != null)
+        {
+          annotations[i] = new Annotation(ann[i]);
+          if (_linecolour != null)
+          {
+            _linecolour = annotations[i].colour;
+          }
+        }
+      }
+    }
+    if (annotation.sequenceRef != null)
+    {
+      this.sequenceRef = annotation.sequenceRef;
+      if (annotation.sequenceMapping != null)
+      {
+        Integer p = null;
+        sequenceMapping = new HashMap<>();
+        Iterator<Integer> pos = annotation.sequenceMapping.keySet()
+                .iterator();
+        while (pos.hasNext())
+        {
+          // could optimise this!
+          p = pos.next();
+          Annotation a = annotation.sequenceMapping.get(p);
+          if (a == null)
+          {
+            continue;
+          }
+          if (ann != null)
+          {
+            for (int i = 0; i < ann.length; i++)
+            {
+              if (ann[i] == a)
+              {
+                sequenceMapping.put(p, annotations[i]);
+              }
+            }
+          }
+        }
+      }
+      else
+      {
+        this.sequenceMapping = null;
+      }
+    }
+    // TODO: check if we need to do this: JAL-952
+    // if (this.isrna=annotation.isrna)
+    {
+      // _rnasecstr=new SequenceFeature[annotation._rnasecstr];
+    }
+    validateRangeAndDisplay(); // construct hashcodes, etc.
+  }
+
+  /**
+   * copy constructor with edit based on the hidden columns marked in colSel
+   * 
+   * @param alignmentAnnotation
+   * @param colSel
+   */
+  public AlignmentAnnotation(AlignmentAnnotation alignmentAnnotation,
+          HiddenColumns hidden)
+  {
+    this(alignmentAnnotation);
+    if (annotations == null)
+    {
+      return;
+    }
+    makeVisibleAnnotation(hidden);
+  }
+
+  /**
+   * Creates a new AlignmentAnnotation object.
+   * 
+   * @param label
+   *          DOCUMENT ME!
+   * @param description
+   *          DOCUMENT ME!
+   * @param annotations
+   *          DOCUMENT ME!
+   * @param min
+   *          DOCUMENT ME!
+   * @param max
+   *          DOCUMENT ME!
+   * @param winLength
+   *          DOCUMENT ME!
+   */
+  public AlignmentAnnotation(String label, String description,
+          Annotation[] annotations, float min, float max, int graphType)
+  {
+    setAnnotationId();
+    // graphs are not editable
+    editable = graphType == 0;
+
+    this.label = label;
+    this.description = description;
+    this.annotations = annotations;
+    graph = graphType;
+    graphMin = min;
+    graphMax = max;
+    validateRangeAndDisplay();
+  }
+
+  /**
+   * Score only annotation
+   * 
+   * @param label
+   * @param description
+   * @param score
+   */
+  public AlignmentAnnotation(String label, String description, double score)
+  {
+    this(label, description, null);
+    setScore(score);
+  }
+
+  /**
+   * Updates the _rnasecstr field Determines the positions that base pair and
+   * the positions of helices based on secondary structure from a Stockholm file
+   * 
+   * @param rnaAnnotation
+   */
+  private void _updateRnaSecStr(CharSequence rnaAnnotation)
+  {
+    try
+    {
+      _rnasecstr = Rna.getHelixMap(rnaAnnotation);
+      invalidrnastruc = -1;
+    } catch (WUSSParseException px)
+    {
+      // DEBUG System.out.println(px);
+      invalidrnastruc = px.getProblemPos();
+    }
+    if (invalidrnastruc > -1)
+    {
+      return;
+    }
+
+    if (_rnasecstr != null && _rnasecstr.length > 0)
+    {
+      // show all the RNA secondary structure annotation symbols.
+      isrna = true;
+      showAllColLabels = true;
+      scaleColLabel = true;
+      _markRnaHelices();
+    }
+    // System.out.println("featuregroup " + _rnasecstr[0].getFeatureGroup());
+
+  }
+
+  private void _markRnaHelices()
+  {
+    int mxval = 0;
+    // Figure out number of helices
+    // Length of rnasecstr is the number of pairs of positions that base pair
+    // with each other in the secondary structure
+    for (int x = 0; x < _rnasecstr.length; x++)
+    {
+
+      /*
+       * System.out.println(this.annotation._rnasecstr[x] + " Begin" +
+       * this.annotation._rnasecstr[x].getBegin());
+       */
+      // System.out.println(this.annotation._rnasecstr[x].getFeatureGroup());
+      int val = 0;
+      try
+      {
+        val = Integer.valueOf(_rnasecstr[x].getFeatureGroup());
+        if (mxval < val)
+        {
+          mxval = val;
+        }
+      } catch (NumberFormatException q)
+      {
+      }
+      ;
+
+      annotations[_rnasecstr[x].getBegin()].value = val;
+      annotations[_rnasecstr[x].getEnd()].value = val;
+
+      // annotations[_rnasecstr[x].getBegin()].displayCharacter = "" + val;
+      // annotations[_rnasecstr[x].getEnd()].displayCharacter = "" + val;
+    }
+    setScore(mxval);
+  }
+
+  /**
    * Checks if annotation labels represent secondary structures
    * 
    */
@@ -521,38 +690,6 @@ public class AlignmentAnnotation
   }
 
   /**
-   * Creates a new AlignmentAnnotation object.
-   * 
-   * @param label
-   *          DOCUMENT ME!
-   * @param description
-   *          DOCUMENT ME!
-   * @param annotations
-   *          DOCUMENT ME!
-   * @param min
-   *          DOCUMENT ME!
-   * @param max
-   *          DOCUMENT ME!
-   * @param winLength
-   *          DOCUMENT ME!
-   */
-  public AlignmentAnnotation(String label, String description,
-          Annotation[] annotations, float min, float max, int graphType)
-  {
-    setAnnotationId();
-    // graphs are not editable
-    editable = graphType == 0;
-
-    this.label = label;
-    this.description = description;
-    this.annotations = annotations;
-    graph = graphType;
-    graphMin = min;
-    graphMax = max;
-    validateRangeAndDisplay();
-  }
-
-  /**
    * checks graphMin and graphMax, secondary structure symbols, sets graphType
    * appropriately, sets null labels to the empty string if appropriate.
    */
@@ -633,113 +770,6 @@ public class AlignmentAnnotation
   }
 
   /**
-   * Copy constructor creates a new independent annotation row with the same
-   * associated sequenceRef
-   * 
-   * @param annotation
-   */
-  public AlignmentAnnotation(AlignmentAnnotation annotation)
-  {
-    setAnnotationId();
-    this.label = new String(annotation.label);
-    if (annotation.description != null)
-    {
-      this.description = new String(annotation.description);
-    }
-    this.graphMin = annotation.graphMin;
-    this.graphMax = annotation.graphMax;
-    this.graph = annotation.graph;
-    this.graphHeight = annotation.graphHeight;
-    this.graphGroup = annotation.graphGroup;
-    this.groupRef = annotation.groupRef;
-    this.editable = annotation.editable;
-    this.autoCalculated = annotation.autoCalculated;
-    this.hasIcons = annotation.hasIcons;
-    this.hasText = annotation.hasText;
-    this.height = annotation.height;
-    this.label = annotation.label;
-    this.padGaps = annotation.padGaps;
-    this.visible = annotation.visible;
-    this.centreColLabels = annotation.centreColLabels;
-    this.scaleColLabel = annotation.scaleColLabel;
-    this.showAllColLabels = annotation.showAllColLabels;
-    this.calcId = annotation.calcId;
-    if (annotation.properties != null)
-    {
-      properties = new HashMap<>();
-      for (Map.Entry<String, String> val : annotation.properties.entrySet())
-      {
-        properties.put(val.getKey(), val.getValue());
-      }
-    }
-    if (this.hasScore = annotation.hasScore)
-    {
-      this.score = annotation.score;
-    }
-    if (annotation.threshold != null)
-    {
-      threshold = new GraphLine(annotation.threshold);
-    }
-    Annotation[] ann = annotation.annotations;
-    if (annotation.annotations != null)
-    {
-      this.annotations = new Annotation[ann.length];
-      for (int i = 0; i < ann.length; i++)
-      {
-        if (ann[i] != null)
-        {
-          annotations[i] = new Annotation(ann[i]);
-          if (_linecolour != null)
-          {
-            _linecolour = annotations[i].colour;
-          }
-        }
-      }
-    }
-    if (annotation.sequenceRef != null)
-    {
-      this.sequenceRef = annotation.sequenceRef;
-      if (annotation.sequenceMapping != null)
-      {
-        Integer p = null;
-        sequenceMapping = new HashMap<>();
-        Iterator<Integer> pos = annotation.sequenceMapping.keySet()
-                .iterator();
-        while (pos.hasNext())
-        {
-          // could optimise this!
-          p = pos.next();
-          Annotation a = annotation.sequenceMapping.get(p);
-          if (a == null)
-          {
-            continue;
-          }
-          if (ann != null)
-          {
-            for (int i = 0; i < ann.length; i++)
-            {
-              if (ann[i] == a)
-              {
-                sequenceMapping.put(p, annotations[i]);
-              }
-            }
-          }
-        }
-      }
-      else
-      {
-        this.sequenceMapping = null;
-      }
-    }
-    // TODO: check if we need to do this: JAL-952
-    // if (this.isrna=annotation.isrna)
-    {
-      // _rnasecstr=new SequenceFeature[annotation._rnasecstr];
-    }
-    validateRangeAndDisplay(); // construct hashcodes, etc.
-  }
-
-  /**
    * clip the annotation to the columns given by startRes and endRes (inclusive)
    * and prune any existing sequenceMapping to just those columns.
    * 
@@ -1097,36 +1127,6 @@ public class AlignmentAnnotation
     return hasScore || !Double.isNaN(score);
   }
 
-  /**
-   * Score only annotation
-   * 
-   * @param label
-   * @param description
-   * @param score
-   */
-  public AlignmentAnnotation(String label, String description, double score)
-  {
-    this(label, description, null);
-    setScore(score);
-  }
-
-  /**
-   * copy constructor with edit based on the hidden columns marked in colSel
-   * 
-   * @param alignmentAnnotation
-   * @param colSel
-   */
-  public AlignmentAnnotation(AlignmentAnnotation alignmentAnnotation,
-          HiddenColumns hidden)
-  {
-    this(alignmentAnnotation);
-    if (annotations == null)
-    {
-      return;
-    }
-    makeVisibleAnnotation(hidden);
-  }
-
   public void setPadGaps(boolean padgaps, char gapchar)
   {
     this.padGaps = padgaps;
@@ -1185,7 +1185,7 @@ public class AlignmentAnnotation
   /**
    * machine readable ID string indicating what generated this annotation
    */
-  protected String calcId = "";
+  private String calcId = "";
 
   /**
    * properties associated with the calcId
@@ -1586,8 +1586,7 @@ public class AlignmentAnnotation
           Iterable<AlignmentAnnotation> list, SequenceI seq, String calcId,
           String label)
   {
-
-    ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
+    List<AlignmentAnnotation> aa = new ArrayList<>();
     for (AlignmentAnnotation ann : list)
     {
       if ((calcId == null || (ann.getCalcId() != null
@@ -1631,7 +1630,6 @@ public class AlignmentAnnotation
   public static Iterable<AlignmentAnnotation> findAnnotation(
           List<AlignmentAnnotation> list, String calcId)
   {
-
     List<AlignmentAnnotation> aa = new ArrayList<>();
     if (calcId == null)
     {
index 5fb16d6..d591f42 100755 (executable)
@@ -504,8 +504,6 @@ public interface AlignmentI extends AnnotatedCollectionI
    *          - null or specific sequence reference
    * @param groupRef
    *          - null or specific group reference
-   * @param method
-   *          - CalcId for the annotation (must match)
    * 
    * @return existing annotation matching the given attributes
    */
@@ -588,6 +586,16 @@ public interface AlignmentI extends AnnotatedCollectionI
   public void setHiddenColumns(HiddenColumns cols);
 
   /**
+   * Insert a sequence at a position in an alignment
+   * 
+   * @param i
+   *          The index of the position.
+   * @param snew
+   *          The new sequence.
+   */
+  void insertSequenceAt(int i, SequenceI snew);
+
+  /**
    * Set the first sequence as representative and hide its insertions. Typically
    * used when loading JPred files.
    */
@@ -607,5 +615,4 @@ public interface AlignmentI extends AnnotatedCollectionI
    */
   public HiddenColumns propagateInsertions(SequenceI profileseq,
           AlignmentView input);
-
 }
index 6d09145..ef46d79 100755 (executable)
@@ -80,7 +80,7 @@ public class AlignmentOrder
    */
   public AlignmentOrder(AlignmentI orderFrom)
   {
-    Order = new ArrayList<SequenceI>();
+    Order = new ArrayList<>();
 
     for (SequenceI seq : orderFrom.getSequences())
     {
@@ -96,7 +96,7 @@ public class AlignmentOrder
    */
   public AlignmentOrder(SequenceI[] orderFrom)
   {
-    Order = new ArrayList<SequenceI>(Arrays.asList(orderFrom));
+    Order = new ArrayList<>(Arrays.asList(orderFrom));
   }
 
   /**
index 2963fd5..878f22a 100644 (file)
@@ -61,4 +61,6 @@ public interface AnnotatedCollectionI extends SequenceCollectionI
    *         alignment, parent group).
    */
   AnnotatedCollectionI getContext();
+
+  
 }
diff --git a/src/jalview/datamodel/HMMNode.java b/src/jalview/datamodel/HMMNode.java
new file mode 100644 (file)
index 0000000..b646eee
--- /dev/null
@@ -0,0 +1,148 @@
+package jalview.datamodel;
+
+/**
+ * stores data for each node in the hmm model
+ * @author TZVanaalten
+ *
+ */
+public class HMMNode
+{
+  //contains the match emissions for each symbol 
+  double[] matchEmissions;
+
+  //contains the insert emissions for each symbol 
+  double[] insertEmissions;
+
+  // contains the state transitions for each possible transition. These are mm,
+  // mi, md, im, ii, dm and dd in order
+  double[] stateTransitions;
+  
+  //annotations
+  int residueNumber;
+  char consensusResidue;
+  char referenceAnnotation;
+  char maskValue;
+  char consensusStructure;
+
+  /**
+   * Constructor
+   */
+  public HMMNode()
+  {
+  }
+
+  public double[] getMatchEmissions()
+  {
+    return matchEmissions;
+  }
+
+  double getMatchEmission(int symbolIndex)
+  {
+    return matchEmissions[symbolIndex];
+  }
+
+  public void setMatchEmissions(double[] matches)
+  {
+    this.matchEmissions = matches;
+  }
+
+  public double[] getInsertEmissions()
+  {
+    return insertEmissions;
+  }
+
+  double getInsertEmission(int symbolIndex)
+  {
+    return insertEmissions[symbolIndex];
+  }
+
+  public void setInsertEmissions(double[] insertEmissionsL)
+  {
+    this.insertEmissions = insertEmissionsL;
+  }
+
+  public double[] getStateTransitions()
+  {
+    return stateTransitions;
+  }
+
+  double getStateTransition(int transition)
+  {
+    return stateTransitions[transition];
+  }
+
+  public void setStateTransitions(double[] stateTransitionsM)
+  {
+    this.stateTransitions = stateTransitionsM;
+  }
+
+  int getResidueNumber()
+  {
+    return residueNumber;
+  }
+  public void setResidueNumber(int resNo)
+  {
+    this.residueNumber = resNo;
+  }
+
+  char getConsensusResidue()
+  {
+    return consensusResidue;
+  }
+  public void setConsensusResidue(char consensusResidue)
+  {
+    this.consensusResidue = consensusResidue;
+  }
+
+  char getReferenceAnnotation()
+  {
+    return referenceAnnotation;
+  }
+  public void setReferenceAnnotation(char referenceAnnotation)
+  {
+    this.referenceAnnotation = referenceAnnotation;
+  }
+
+  char getMaskValue()
+  {
+    return maskValue;
+  }
+  public void setMaskValue(char maskValue)
+  {
+    this.maskValue = maskValue;
+  }
+
+  char getConsensusStructure()
+  {
+    return consensusStructure;
+  }
+  public void setConsensusStructure(char consensusStructure)
+  {
+    this.consensusStructure = consensusStructure;
+  }
+
+  /**
+   * Answers the symbol index of the symbol with the highest match emission
+   * probability (first symbol in case of a tie). Note this object stores
+   * probabilities, not the negative logarithms as in the HMM file.
+   * 
+   * @return
+   */
+  int getMaxMatchEmissionIndex()
+  {
+    int maxIndex = 0;
+    double max = 0D;
+
+    for (int i = 0; i < matchEmissions.length; i++)
+    {
+      if (matchEmissions[i] > max)
+      {
+        max = matchEmissions[i];
+        maxIndex = i;
+      }
+    }
+    return maxIndex;
+  }
+}
+   
+  
diff --git a/src/jalview/datamodel/HiddenMarkovModel.java b/src/jalview/datamodel/HiddenMarkovModel.java
new file mode 100644 (file)
index 0000000..e3eb160
--- /dev/null
@@ -0,0 +1,637 @@
+package jalview.datamodel;
+
+import jalview.io.HMMFile;
+import jalview.schemes.ResidueProperties;
+import jalview.util.Comparison;
+import jalview.util.MapList;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Data structure which stores a hidden Markov model
+ * 
+ * @author TZVanaalten
+ * 
+ */
+public class HiddenMarkovModel
+{
+  private static final char GAP_DASH = '-';
+
+  public final static String YES = "yes";
+
+  public final static String NO = "no";
+
+  public static final int MATCHTOMATCH = 0;
+
+  public static final int MATCHTOINSERT = 1;
+
+  public static final int MATCHTODELETE = 2;
+
+  public static final int INSERTTOMATCH = 3;
+
+  public static final int INSERTTOINSERT = 4;
+
+  public static final int DELETETOMATCH = 5;
+
+  public static final int DELETETODELETE = 6;
+
+  private static final double LOG2 = Math.log(2);
+
+  /*
+   * properties read from HMM file header lines
+   */
+  private Map<String, String> fileProperties = new HashMap<>();
+
+  private String fileHeader;
+  
+  /*
+   * the symbols used in this model e.g. "ACGT"
+   */
+  private String alphabet;
+
+  /*
+   * symbol lookup index into the alphabet for 'A' to 'Z'
+   */
+  private int[] symbolIndexLookup = new int['Z' - 'A' + 1];
+
+  /*
+   * Nodes in the model. The begin node is at index 0, and contains 
+   * average emission probabilities for each symbol.
+   */
+  private List<HMMNode> nodes = new ArrayList<>();
+
+  /*
+   * the aligned HMM consensus sequence extracted from the HMM profile
+   */
+  private SequenceI hmmSeq;
+
+  /*
+   * mapping from HMM nodes to residues of the hmm consensus sequence
+   */
+  private Mapping mapToHmmConsensus;
+
+  /**
+   * Constructor
+   */
+  public HiddenMarkovModel()
+  {
+  }
+
+  /**
+   * Copy constructor given a new aligned sequence with which to associate the
+   * HMM profile
+   * 
+   * @param hmm
+   * @param sq
+   */
+  public HiddenMarkovModel(HiddenMarkovModel hmm, SequenceI sq)
+  {
+    super();
+    this.fileProperties = new HashMap<>(hmm.fileProperties);
+    this.alphabet = hmm.alphabet;
+    this.nodes = new ArrayList<>(hmm.nodes);
+    this.symbolIndexLookup = hmm.symbolIndexLookup;
+    this.fileHeader = new String(hmm.fileHeader);
+    this.hmmSeq = sq;
+    if (sq.getDatasetSequence() == hmm.mapToHmmConsensus.getTo())
+    {
+      // same dataset sequence e.g. after realigning search results
+      this.mapToHmmConsensus = hmm.mapToHmmConsensus;
+    }
+    else
+    {
+      // different dataset sequence e.g. after loading HMM from project
+      this.mapToHmmConsensus = new Mapping(sq.getDatasetSequence(),
+              hmm.mapToHmmConsensus.getMap());
+    }
+  }
+
+  /**
+   * Returns the information content at a specified column, calculated as the
+   * sum (over possible symbols) of the log ratio
+   * 
+   * <pre>
+   *  log(emission probability / background probability) / log(2)
+   * </pre>
+   * 
+   * @param column
+   *          column position (base 0)
+   * @return
+   */
+  public float getInformationContent(int column)
+  {
+    float informationContent = 0f;
+
+    for (char symbol : getSymbols().toCharArray())
+    {
+      float freq = ResidueProperties.backgroundFrequencies
+              .get(getAlphabetType()).get(symbol);
+      float prob = (float) getMatchEmissionProbability(column, symbol);
+      informationContent += prob * Math.log(prob / freq);
+    }
+
+    informationContent = informationContent / (float) LOG2;
+
+    return informationContent;
+  }
+
+  /**
+   * Gets the file header of the .hmm file this model came from
+   * 
+   * @return
+   */
+  public String getFileHeader()
+  {
+    return fileHeader;
+  }
+
+  /**
+   * Sets the file header of this model.
+   * 
+   * @param header
+   */
+  public void setFileHeader(String header)
+  {
+    fileHeader = header;
+  }
+
+  /**
+   * Returns the symbols used in this hidden Markov model
+   * 
+   * @return
+   */
+  public String getSymbols()
+  {
+    return alphabet;
+  }
+  
+  /**
+   * Gets the node in the hidden Markov model at the specified position.
+   * 
+   * @param nodeIndex
+   *          The index of the node requested. Node 0 optionally contains the
+   *          average match emission probabilities across the entire model, and
+   *          always contains the insert emission probabilities and state
+   *          transition probabilities for the begin node. Node 1 contains the
+   *          first node in the HMM that can correspond to a column in the
+   *          alignment.
+   * @return
+   */
+  public HMMNode getNode(int nodeIndex)
+  {
+    return nodes.get(nodeIndex);
+  }
+
+  /**
+   * Returns the name of the sequence alignment on which the HMM is based.
+   * 
+   * @return
+   */
+  public String getName()
+  {
+    return fileProperties.get(HMMFile.NAME);
+  }
+  
+  /**
+   * Answers the string value of the property (parsed from an HMM file) for the
+   * given key, or null if the property is not present
+   * 
+   * @param key
+   * @return
+   */
+  public String getProperty(String key)
+  {
+    return fileProperties.get(key);
+  }
+
+  /**
+   * Answers true if the property with the given key is present with a value of
+   * "yes" (not case-sensitive), else false
+   * 
+   * @param key
+   * @return
+   */
+  public boolean getBooleanProperty(String key)
+  {
+    return YES.equalsIgnoreCase(fileProperties.get(key));
+  }
+
+  /**
+   * Returns the length of the hidden Markov model. The value returned is the
+   * LENG property if specified, else the number of nodes, excluding the begin
+   * node (which should be the same thing).
+   * 
+   * @return
+   */
+  public int getLength()
+  {
+    if (fileProperties.get(HMMFile.LENGTH) == null)
+    {
+      return nodes.size() - 1; // not counting BEGIN node
+    }
+    return Integer.parseInt(fileProperties.get(HMMFile.LENGTH));
+  }
+
+  /**
+   * Returns the value of mandatory property "ALPH" - "amino", "DNA", "RNA" are
+   * the options. Other alphabets may be added.
+   * 
+   * @return
+   */
+  public String getAlphabetType()
+  {
+    return fileProperties.get(HMMFile.ALPHABET);
+  }
+
+  /**
+   * Sets the model alphabet to the symbols in the given string (ignoring any
+   * whitespace), and returns the number of symbols
+   * 
+   * @param symbols
+   */
+  public int setAlphabet(String symbols)
+  {
+    String trimmed = symbols.toUpperCase().replaceAll("\\s", "");
+    int count = trimmed.length();
+    alphabet = trimmed;
+    symbolIndexLookup = new int['Z' - 'A' + 1];
+    Arrays.fill(symbolIndexLookup, -1);
+    int ignored = 0;
+
+    /*
+     * save the symbols in order, and a quick lookup of symbol position
+     */
+    for (short i = 0; i < count; i++)
+    {
+      char symbol = trimmed.charAt(i);
+      if (symbol >= 'A' && symbol <= 'Z'
+              && symbolIndexLookup[symbol - 'A'] == -1)
+      {
+        symbolIndexLookup[symbol - 'A'] = i;
+      }
+      else
+      {
+        System.err
+                .println(
+                        "Unexpected or duplicated character in HMM ALPHabet: "
+                                + symbol);
+        ignored++;
+      }
+    }
+    return count - ignored;
+  }
+
+  /**
+   * Answers the node of the model corresponding to an aligned column position
+   * (0...), or null if there is no such node
+   * 
+   * @param column
+   * @return
+   */
+  HMMNode getNodeForColumn(int column)
+  {
+    /*
+     * if the hmm consensus is gapped at the column,
+     * there is no corresponding node
+     */
+    if (Comparison.isGap(hmmSeq.getCharAt(column)))
+    {
+      return null;
+    }
+
+    /*
+     * find the node (if any) that is mapped to the
+     * consensus sequence residue position at the column
+     */
+    int seqPos = hmmSeq.findPosition(column);
+    int[] nodeNo = mapToHmmConsensus.getMap().locateInFrom(seqPos, seqPos);
+    if (nodeNo != null)
+    {
+      return getNode(nodeNo[0]);
+    }
+    return null;
+  }
+
+  /**
+   * Gets the match emission probability for a given symbol at a column in the
+   * alignment.
+   * 
+   * @param alignColumn
+   *          The index of the alignment column, starting at index 0. Index 0
+   *          usually corresponds to index 1 in the HMM.
+   * @param symbol
+   *          The symbol for which the desired probability is being requested.
+   * @return
+   * 
+   */
+  public double getMatchEmissionProbability(int alignColumn, char symbol)
+  {
+    HMMNode node = getNodeForColumn(alignColumn);
+    int symbolIndex = getSymbolIndex(symbol);
+    if (node != null && symbolIndex != -1)
+    {
+      return node.getMatchEmission(symbolIndex);
+    }
+    return 0D;
+  }
+
+  /**
+   * Gets the insert emission probability for a given symbol at a column in the
+   * alignment.
+   * 
+   * @param alignColumn
+   *          The index of the alignment column, starting at index 0. Index 0
+   *          usually corresponds to index 1 in the HMM.
+   * @param symbol
+   *          The symbol for which the desired probability is being requested.
+   * @return
+   * 
+   */
+  public double getInsertEmissionProbability(int alignColumn, char symbol)
+  {
+    HMMNode node = getNodeForColumn(alignColumn);
+    int symbolIndex = getSymbolIndex(symbol);
+    if (node != null && symbolIndex != -1)
+    {
+      return node.getInsertEmission(symbolIndex);
+    }
+    return 0D;
+  }
+  
+  /**
+   * Gets the state transition probability for a given symbol at a column in the
+   * alignment.
+   * 
+   * @param alignColumn
+   *          The index of the alignment column, starting at index 0. Index 0
+   *          usually corresponds to index 1 in the HMM.
+   * @param symbol
+   *          The symbol for which the desired probability is being requested.
+   * @return
+   * 
+   */
+  public double getStateTransitionProbability(int alignColumn,
+          int transition)
+  {
+    HMMNode node = getNodeForColumn(alignColumn);
+    if (node != null)
+    {
+      return node.getStateTransition(transition);
+    }
+    return 0D;
+  }
+  
+  /**
+   * Returns the sequence position linked to the node at the given index. This
+   * corresponds to an aligned column position (counting from 1).
+   * 
+   * @param nodeIndex
+   *          The index of the node, starting from index 1. Index 0 is the begin
+   *          node, which does not correspond to a column in the alignment.
+   * @return
+   */
+  public int getNodeMapPosition(int nodeIndex)
+  {
+    return nodes.get(nodeIndex).getResidueNumber();
+  }
+  
+  /**
+   * Returns the consensus residue at the specified node.
+   * 
+   * @param nodeIndex
+   *          The index of the specified node.
+   * @return
+   */
+  public char getConsensusResidue(int nodeIndex)
+  {
+   char value = nodes.get(nodeIndex).getConsensusResidue();
+   return value;
+  }
+  
+  /**
+   * Returns the reference annotation at the specified node.
+   * 
+   * @param nodeIndex
+   *          The index of the specified node.
+   * @return
+   */
+  public char getReferenceAnnotation(int nodeIndex)
+  {
+   char value = nodes.get(nodeIndex).getReferenceAnnotation();
+   return value;
+  }
+  
+  /**
+   * Returns the mask value at the specified node.
+   * 
+   * @param nodeIndex
+   *          The index of the specified node.
+   * @return
+   */
+  public char getMaskedValue(int nodeIndex)
+  {
+   char value = nodes.get(nodeIndex).getMaskValue();
+   return value;
+  }
+  
+  /**
+   * Returns the consensus structure at the specified node.
+   * 
+   * @param nodeIndex
+   *          The index of the specified node.
+   * @return
+   */
+  public char getConsensusStructure(int nodeIndex)
+  {
+   char value = nodes.get(nodeIndex).getConsensusStructure();
+   return value;
+  }
+  
+  /**
+   * Sets a property read from an HMM file
+   * 
+   * @param key
+   * @param value
+   */
+  public void setProperty(String key, String value)
+  {
+    fileProperties.put(key, value);
+  }
+
+  /**
+   * Temporary implementation, should not be used.
+   * 
+   * @return
+   */
+  public String getViterbi()
+  {
+    String value;
+    value = fileProperties.get(HMMFile.VITERBI);
+    return value;
+  }
+
+  /**
+   * Temporary implementation, should not be used.
+   * 
+   * @return
+   */
+  public String getMSV()
+  {
+    String value;
+    value = fileProperties.get(HMMFile.MSV);
+    return value;
+  }
+
+  /**
+   * Temporary implementation, should not be used.
+   * 
+   * @return
+   */
+  public String getForward()
+  {
+    String value;
+    value = fileProperties.get(HMMFile.FORWARD);
+    return value;
+  }
+
+  /**
+   * Constructs the consensus sequence based on the most probable symbol at each
+   * position. Gap characters are inserted for discontinuities in the node map
+   * numbering (if provided), else an ungapped sequence is generated.
+   * <p>
+   * A mapping between the HMM nodes and residue positions of the sequence is
+   * also built and saved.
+   * 
+   * @return
+   */
+  void buildConsensusSequence()
+  {
+    List<int[]> toResidues = new ArrayList<>();
+
+    /*
+     * if the HMM provided a map to sequence, use those start/end values,
+     * else just treat it as for a contiguous sequence numbered from 1
+     */
+    boolean hasMap = getBooleanProperty(HMMFile.MAP);
+    int start = hasMap ? getNode(1).getResidueNumber() : 1;
+    int endResNo = hasMap ? getNode(nodes.size() - 1).getResidueNumber()
+            : (start + getLength() - 1);
+    char[] sequence = new char[endResNo - start + 1];
+
+    int lastResNo = start - 1;
+    int seqOffset = 0;
+    int gapCount = 0;
+
+    for (int nodeNo = 1; nodeNo < nodes.size(); nodeNo++)
+    {
+      HMMNode node = nodes.get(nodeNo);
+      final int resNo = hasMap ? node.getResidueNumber() : lastResNo + 1;
+
+      /*
+       * insert gaps if map numbering is not continuous
+       */
+      while (resNo > lastResNo + 1)
+      {
+        sequence[seqOffset++] = '-';
+        lastResNo++;
+        gapCount++;
+      }
+      char consensusResidue = node.getConsensusResidue();
+      if (GAP_DASH == consensusResidue)
+      {
+        /*
+         * no residue annotation in HMM - scan for the symbol
+         * with the highest match emission probability
+         */
+        int symbolIndex = node.getMaxMatchEmissionIndex();
+        consensusResidue = alphabet.charAt(symbolIndex);
+        if (node.getMatchEmission(symbolIndex) < 0.5D)
+        {
+          // follow convention of lower case if match emission prob < 0.5
+          consensusResidue = Character.toLowerCase(consensusResidue);
+        }
+      }
+      sequence[seqOffset++] = consensusResidue;
+      lastResNo = resNo;
+    }
+
+    Sequence seq = new Sequence(getName(), sequence, start,
+            lastResNo - gapCount);
+    seq.createDatasetSequence();
+    seq.setHMM(this);
+    this.hmmSeq = seq;
+
+    /*
+     * construct and store Mapping of nodes to residues
+     * note as constructed this is just an identity mapping, 
+     * but it allows for greater flexibility in future
+     */
+    List<int[]> fromNodes = new ArrayList<>();
+    fromNodes.add(new int[] { 1, getLength() });
+    toResidues.add(new int[] { seq.getStart(), seq.getEnd() });
+    MapList mapList = new MapList(fromNodes, toResidues, 1, 1);
+    mapToHmmConsensus = new Mapping(seq.getDatasetSequence(), mapList);
+  }
+
+
+  /**
+   * Answers the aligned consensus sequence for the profile. Note this will
+   * return null if called before <code>setNodes</code> has been called.
+   * 
+   * @return
+   */
+  public SequenceI getConsensusSequence()
+  {
+    return hmmSeq;
+  }
+
+  /**
+   * Answers the index position (0...) of the given symbol, or -1 if not a valid
+   * symbol for this HMM
+   * 
+   * @param symbol
+   * @return
+   */
+  private int getSymbolIndex(char symbol)
+  {
+    /*
+     * symbolIndexLookup holds the index for 'A' to 'Z'
+     */
+    char c = Character.toUpperCase(symbol);
+    if ('A' <= c && c <= 'Z')
+    {
+      return symbolIndexLookup[c - 'A'];
+    }
+    return -1;
+  }
+
+  /**
+   * Sets the nodes of this HMM, and also extracts the HMM consensus sequence
+   * and a mapping between node numbers and sequence positions
+   * 
+   * @param nodeList
+   */
+  public void setNodes(List<HMMNode> nodeList)
+  {
+    nodes = nodeList;
+    if (nodes.size() > 1)
+    {
+      buildConsensusSequence();
+    }
+  }
+
+  /**
+   * Sets the aligned consensus sequence this HMM is the model for
+   * 
+   * @param hmmSeq
+   */
+  public void setHmmSeq(SequenceI hmmSeq)
+  {
+    this.hmmSeq = hmmSeq;
+  }
+}
+
index 74eb887..047b7e7 100644 (file)
@@ -25,6 +25,8 @@ import jalview.util.Format;
 import jalview.util.QuickSort;
 import jalview.util.SparseCount;
 
+import java.util.List;
+
 /**
  * A class to count occurrences of residues in a profile, optimised for speed
  * and memory footprint.
@@ -148,6 +150,24 @@ public class ResidueCount
   }
 
   /**
+   * A constructor that counts frequency of all symbols (including gaps) in the
+   * sequences (not case-sensitive)
+   * 
+   * @param sequences
+   */
+  public ResidueCount(List<SequenceI> sequences)
+  {
+    this();
+    for (SequenceI seq : sequences)
+    {
+      for (int i = 0; i < seq.getLength(); i++)
+      {
+        add(seq.getCharAt(i));
+      }
+    }
+  }
+
+  /**
    * Increments the count for the given character. The supplied character may be
    * upper or lower case but counts are for the upper case only. Gap characters
    * (space, ., -) are all counted together.
@@ -640,4 +660,19 @@ public class ResidueCount
     sb.append("]");
     return sb.toString();
   }
+
+  /**
+   * Answers the total count for all symbols (excluding gaps)
+   * 
+   * @return
+   */
+  public int getTotalResidueCount()
+  {
+    int total = 0;
+    for (char symbol : this.getSymbolCounts().symbols)
+    {
+      total += getCount(symbol);
+    }
+    return total;
+  }
 }
index 33de452..7972626 100755 (executable)
@@ -28,6 +28,7 @@ import jalview.util.Comparison;
 import jalview.util.DBRefUtils;
 import jalview.util.MapList;
 import jalview.util.StringUtils;
+import jalview.workers.InformationThread;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -62,6 +63,10 @@ public class Sequence extends ASequence implements SequenceI
 
   int end;
 
+  HiddenMarkovModel hmm;
+
+  boolean isHMMConsensusSequence = false;
+
   Vector<PDBEntry> pdbIds;
 
   String vamsasId;
@@ -338,6 +343,11 @@ public class Sequence extends ASequence implements SequenceI
         this.addPDBId(new PDBEntry(pdb));
       }
     }
+    if (seq.getHMM() != null)
+    {
+      this.hmm = new HiddenMarkovModel(seq.getHMM(), this);
+    }
+
   }
 
   @Override
@@ -1802,7 +1812,8 @@ public class Sequence extends ASequence implements SequenceI
     {
       for (AlignmentAnnotation ann : annotation)
       {
-        if (ann.calcId != null && ann.calcId.equals(calcId)
+        String id = ann.getCalcId();
+        if (id != null && id.equals(calcId)
                 && ann.label != null && ann.label.equals(label))
         {
           result.add(ann);
@@ -1900,6 +1911,34 @@ public class Sequence extends ASequence implements SequenceI
     }
   }
 
+  @Override
+  public HiddenMarkovModel getHMM()
+  {
+    return hmm;
+  }
+
+  @Override
+  public void setHMM(HiddenMarkovModel hmm)
+  {
+    this.hmm = hmm;
+  }
+
+  @Override
+  public boolean hasHMMAnnotation()
+  {
+    if (this.annotation == null) {
+      return false;
+    }
+    for (AlignmentAnnotation ann : annotation)
+    {
+      if (InformationThread.HMM_CALC_ID.equals(ann.getCalcId()))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
   /**
    * {@inheritDoc}
    */
@@ -2064,4 +2103,10 @@ public class Sequence extends ASequence implements SequenceI
     // otherwise, sequence was completely hidden
     return 0;
   }
+
+  @Override
+  public boolean hasHMMProfile()
+  {
+    return hmm != null;
+  }
 }
index f681f11..a280079 100644 (file)
@@ -70,4 +70,12 @@ public interface SequenceCollectionI
    * @return
    */
   boolean isNucleotide();
+
+  /**
+   * Returns the (possibly empty) list of HMM consensus sequences in the
+   * collection
+   * 
+   * @return
+   */
+  List<SequenceI> getHmmSequences();
 }
index 944f263..b558f40 100755 (executable)
@@ -25,6 +25,8 @@ import jalview.analysis.Conservation;
 import jalview.renderer.ResidueShader;
 import jalview.renderer.ResidueShaderI;
 import jalview.schemes.ColourSchemeI;
+import jalview.util.MessageManager;
+import jalview.workers.InformationThread;
 
 import java.awt.Color;
 import java.beans.PropertyChangeListener;
@@ -43,116 +45,115 @@ import java.util.Map;
 public class SequenceGroup implements AnnotatedCollectionI
 {
   // TODO ideally this event notification functionality should be separated into
-  // a
-  // subclass of ViewportProperties similarly to ViewportRanges. Done here as
-  // quick fix for JAL-2665
+  // a subclass of ViewportProperties similarly to ViewportRanges.
+  // Done here as a quick fix for JAL-2665
   public static final String SEQ_GROUP_CHANGED = "Sequence group changed";
 
-  protected PropertyChangeSupport changeSupport = new PropertyChangeSupport(
-          this);
+  private String groupName;
 
-  public void addPropertyChangeListener(PropertyChangeListener listener)
-  {
-    changeSupport.addPropertyChangeListener(listener);
-  }
+  private String description;
 
-  public void removePropertyChangeListener(PropertyChangeListener listener)
-  {
-    changeSupport.removePropertyChangeListener(listener);
-  }
-  // end of event notification functionality initialisation
+  private AnnotatedCollectionI context;
 
-  String groupName;
+  private Conservation conservationData;
 
-  String description;
+  private ProfilesI consensusProfiles;
 
-  Conservation conserve;
+  private ProfilesI hmmProfiles;
 
-  boolean displayBoxes = true;
+  private boolean displayBoxes = true;
 
-  boolean displayText = true;
+  private boolean displayText = true;
 
-  boolean colourText = false;
+  private boolean colourText = false;
 
-  /**
-   * True if the group is defined as a group on the alignment, false if it is
-   * just a selection.
+  /*
+   * true if the group is defined as a group on the alignment, false if it is
+   * just a selection
    */
-  boolean isDefined = false;
+  private boolean isDefined;
 
-  /**
+  /*
    * after Olivier's non-conserved only character display
    */
-  boolean showNonconserved = false;
+  private boolean showNonconserved;
 
-  /**
-   * group members
+  /*
+   * sequences in the group
    */
   private List<SequenceI> sequences = new ArrayList<>();
 
-  /**
+  /*
    * representative sequence for this group (if any)
    */
-  private SequenceI seqrep = null;
+  private SequenceI seqrep;
 
-  int width = -1;
+  private int width = -1;
 
-  /**
-   * Colourscheme applied to group if any
+  /*
+   * colour scheme applied to group if any
    */
   public ResidueShaderI cs;
 
   // start column (base 0)
-  int startRes = 0;
+  private int startRes;
 
   // end column (base 0)
-  int endRes = 0;
+  private int endRes;
 
   public Color outlineColour = Color.black;
 
-  public Color idColour = null;
+  public Color idColour;
 
-  public int thresholdTextColour = 0;
+  public int thresholdTextColour;
 
   public Color textColour = Color.black;
 
   public Color textColour2 = Color.white;
 
-  /**
-   * consensus calculation property
+  /*
+   * properties for consensus annotation
    */
   private boolean ignoreGapsInConsensus = true;
 
-  /**
-   * consensus calculation property
-   */
-  private boolean showSequenceLogo = false;
+  private boolean showSequenceLogo;
 
-  /**
-   * flag indicating if logo should be rendered normalised
-   */
   private boolean normaliseSequenceLogo;
 
+  private boolean showConsensusHistogram;
+
+  /*
+   * properties for HMM information annotation
+   */
+  private boolean hmmIgnoreBelowBackground = true;
+
+  private boolean hmmUseInfoLetterHeight;
+
+  private boolean hmmShowSequenceLogo;
+
+  private boolean hmmNormaliseSequenceLogo;
+
+  private boolean hmmShowHistogram;
+
   /*
    * visibility of rows or represented rows covered by group
    */
-  private boolean hidereps = false;
+  private boolean hidereps;
 
   /*
    * visibility of columns intersecting this group
    */
-  private boolean hidecols = false;
-
-  AlignmentAnnotation consensus = null;
+  private boolean hidecols;
 
-  AlignmentAnnotation conservation = null;
+  private AlignmentAnnotation consensus;
 
-  private boolean showConsensusHistogram;
+  private AlignmentAnnotation conservation;
 
-  private AnnotatedCollectionI context;
+  private AlignmentAnnotation hmmInformation;
 
   /**
-   * Creates a new SequenceGroup object.
+   * Constructor, assigning a generated default name of "JGroup:" with object
+   * hashcode appended
    */
   public SequenceGroup()
   {
@@ -222,6 +223,9 @@ public class SequenceGroup implements AnnotatedCollectionI
       showSequenceLogo = seqsel.showSequenceLogo;
       normaliseSequenceLogo = seqsel.normaliseSequenceLogo;
       showConsensusHistogram = seqsel.showConsensusHistogram;
+      hmmShowSequenceLogo = seqsel.hmmShowSequenceLogo;
+      hmmNormaliseSequenceLogo = seqsel.hmmNormaliseSequenceLogo;
+      hmmShowHistogram = seqsel.hmmShowHistogram;
       idColour = seqsel.idColour;
       outlineColour = seqsel.outlineColour;
       seqrep = seqsel.seqrep;
@@ -230,7 +234,9 @@ public class SequenceGroup implements AnnotatedCollectionI
       thresholdTextColour = seqsel.thresholdTextColour;
       width = seqsel.width;
       ignoreGapsInConsensus = seqsel.ignoreGapsInConsensus;
-      if (seqsel.conserve != null)
+      hmmIgnoreBelowBackground = seqsel.hmmIgnoreBelowBackground;
+      hmmUseInfoLetterHeight = seqsel.hmmUseInfoLetterHeight;
+      if (seqsel.conservationData != null)
       {
         recalcConservation(); // safer than
         // aaFrequency = (Vector) seqsel.aaFrequency.clone(); // ??
@@ -238,6 +244,19 @@ public class SequenceGroup implements AnnotatedCollectionI
     }
   }
 
+  protected PropertyChangeSupport changeSupport = new PropertyChangeSupport(
+          this);
+
+  public void addPropertyChangeListener(PropertyChangeListener listener)
+  {
+    changeSupport.addPropertyChangeListener(listener);
+  }
+
+  public void removePropertyChangeListener(PropertyChangeListener listener)
+  {
+    changeSupport.removePropertyChangeListener(listener);
+  }
+
   public boolean isShowSequenceLogo()
   {
     return showSequenceLogo;
@@ -488,7 +507,7 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public Conservation getConservation()
   {
-    return conserve;
+    return conservationData;
   }
 
   /**
@@ -499,7 +518,7 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public void setConservation(Conservation c)
   {
-    conserve = c;
+    conservationData = c;
   }
 
   /**
@@ -560,20 +579,22 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public boolean recalcConservation()
   {
-    return recalcConservation(false);
+    return recalcAnnotations(false);
   }
 
   /**
-   * calculate residue conservation for group - but only if necessary. returns
-   * true if the calculation resulted in a visible change to group
+   * Recalculates column consensus, conservation, and HMM annotation for the
+   * group (as applicable). Returns true if the calculation resulted in a
+   * visible change to group.
    * 
    * @param defer
    *          when set, colourschemes for this group are not refreshed after
    *          recalculation
    */
-  public boolean recalcConservation(boolean defer)
+  public boolean recalcAnnotations(boolean defer)
   {
-    if (cs == null && consensus == null && conservation == null)
+    if (cs == null && consensus == null && conservation == null
+            && hmmInformation == null)
     {
       return false;
     }
@@ -584,6 +605,16 @@ public class SequenceGroup implements AnnotatedCollectionI
     {
       ProfilesI cnsns = AAFrequency.calculate(sequences, startRes,
               endRes + 1, showSequenceLogo);
+      if (hmmInformation != null)
+      {
+        HiddenMarkovModel hmm = hmmInformation.sequenceRef.getHMM();
+
+        ProfilesI info = AAFrequency.calculateHMMProfiles(hmm,
+                (endRes + 1) - startRes, startRes, endRes + 1,
+                hmmIgnoreBelowBackground, hmmUseInfoLetterHeight);
+        _updateInformationRow(info);
+        upd = true;
+      }
       if (consensus != null)
       {
         _updateConsensusRow(cnsns, sequences.size());
@@ -656,8 +687,6 @@ public class SequenceGroup implements AnnotatedCollectionI
     c.completeAnnotations(conservation, null, startRes, endRes + 1);
   }
 
-  public ProfilesI consensusData = null;
-
   private void _updateConsensusRow(ProfilesI cnsns, long nseq)
   {
     if (consensus == null)
@@ -666,7 +695,7 @@ public class SequenceGroup implements AnnotatedCollectionI
     }
     consensus.label = "Consensus for " + getName();
     consensus.description = "Percent Identity";
-    consensusData = cnsns;
+    consensusProfiles = cnsns;
     // preserve width if already set
     int aWidth = (consensus.annotations != null)
             ? (endRes < consensus.annotations.length
@@ -684,6 +713,33 @@ public class SequenceGroup implements AnnotatedCollectionI
   }
 
   /**
+   * Recalculates the information content on the HMM annotation
+   * 
+   * @param cnsns
+   */
+  private void _updateInformationRow(ProfilesI cnsns)
+  {
+    if (hmmInformation == null)
+    {
+      createInformationAnnotation();
+    }
+    hmmInformation.description = MessageManager
+            .getString("label.information_description");
+    setHmmProfiles(cnsns);
+    // preserve width if already set
+    int aWidth = (hmmInformation.annotations != null)
+            ? (endRes < hmmInformation.annotations.length
+                    ? hmmInformation.annotations.length : endRes + 1)
+            : endRes + 1;
+    hmmInformation.annotations = null;
+    hmmInformation.annotations = new Annotation[aWidth]; // should be alignment
+                                                      // width
+    hmmInformation.setCalcId(InformationThread.HMM_CALC_ID);
+    AAFrequency.completeInformation(hmmInformation, cnsns, startRes,
+            endRes + 1);
+  }
+
+  /**
    * @param s
    *          sequence to either add or remove from group
    * @param recalc
@@ -1137,6 +1193,22 @@ public class SequenceGroup implements AnnotatedCollectionI
   }
 
   /**
+   * Creates the Hidden Markov Model annotation for this group
+   */
+  void createInformationAnnotation()
+  {
+    hmmInformation = new AlignmentAnnotation("", "", new Annotation[1], 0f,
+            6.25f, AlignmentAnnotation.BAR_GRAPH);
+    hmmInformation.hasText = true;
+    hmmInformation.autoCalculated = false;
+    hmmInformation.groupRef = this;
+    hmmInformation.label = getName();
+    hmmInformation.description = MessageManager
+            .getString("label.information_description");
+    hmmInformation.setCalcId(InformationThread.HMM_CALC_ID);
+  }
+
+  /**
    * set this alignmentAnnotation object as the one used to render consensus
    * annotation
    * 
@@ -1218,11 +1290,31 @@ public class SequenceGroup implements AnnotatedCollectionI
     ignoreGapsInConsensus = state;
   }
 
-  public boolean getIgnoreGapsConsensus()
+  public boolean isIgnoreGapsConsensus()
   {
     return ignoreGapsInConsensus;
   }
 
+  public void setIgnoreBelowBackground(boolean state)
+  {
+    hmmIgnoreBelowBackground = state;
+  }
+
+  public boolean isIgnoreBelowBackground()
+  {
+    return hmmIgnoreBelowBackground;
+  }
+
+  public void setInfoLetterHeight(boolean state)
+  {
+    hmmUseInfoLetterHeight = state;
+  }
+
+  public boolean isUseInfoLetterHeight()
+  {
+    return hmmUseInfoLetterHeight;
+  }
+
   /**
    * @param showSequenceLogo
    *          indicates if a sequence logo is shown for consensus annotation
@@ -1466,4 +1558,70 @@ public class SequenceGroup implements AnnotatedCollectionI
   {
     return (startRes <= apos && endRes >= apos) && sequences.contains(seq);
   }
+
+  public boolean isShowInformationHistogram()
+  {
+    return hmmShowHistogram;
+  }
+
+  public void setShowInformationHistogram(boolean state)
+  {
+    if (hmmShowHistogram != state && hmmInformation != null)
+    {
+      this.hmmShowHistogram = state;
+      // recalcConservation(); TODO don't know what to do here next
+    }
+    this.hmmShowHistogram = state;
+  }
+
+  public boolean isShowHMMSequenceLogo()
+  {
+    return hmmShowSequenceLogo;
+  }
+
+  public void setShowHMMSequenceLogo(boolean state)
+  {
+    hmmShowSequenceLogo = state;
+  }
+
+  public boolean isNormaliseHMMSequenceLogo()
+  {
+    return hmmNormaliseSequenceLogo;
+  }
+
+  public void setNormaliseHMMSequenceLogo(boolean state)
+  {
+    hmmNormaliseSequenceLogo = state;
+  }
+
+  public ProfilesI getConsensusData()
+  {
+    return consensusProfiles;
+  }
+
+  public ProfilesI getHmmProfiles()
+  {
+    return hmmProfiles;
+  }
+
+  public void setHmmProfiles(ProfilesI hmmProfiles)
+  {
+    this.hmmProfiles = hmmProfiles;
+  }
+
+  @Override
+  public List<SequenceI> getHmmSequences()
+  {
+    List<SequenceI> result = new ArrayList<>();
+    for (int i = 0; i < sequences.size(); i++)
+    {
+      SequenceI seq = sequences.get(i);
+      if (seq.hasHMMProfile())
+      {
+        result.add(seq);
+      }
+    }
+    return result;
+  }
+
 }
index 8dce31e..6d34d07 100755 (executable)
@@ -46,6 +46,10 @@ public interface SequenceI extends ASequenceI
    */
   public void setName(String name);
 
+  public HiddenMarkovModel getHMM();
+
+  public void setHMM(HiddenMarkovModel hmm);
+
   /**
    * Get the display name
    */
@@ -496,6 +500,12 @@ public interface SequenceI extends ASequenceI
   public List<DBRefEntry> getPrimaryDBRefs();
 
   /**
+   * Answers true if the sequence has annotation for Hidden Markov Model
+   * information content, else false
+   */
+  boolean hasHMMAnnotation();
+
+  /**
    * Returns a (possibly empty) list of sequence features that overlap the given
    * alignment column range, optionally restricted to one or more specified
    * feature types. If the range is all gaps, then features which enclose it are
@@ -532,7 +542,7 @@ public interface SequenceI extends ASequenceI
    * @param c1
    * @param c2
    */
-  public int replace(char c1, char c2);
+  int replace(char c1, char c2);
 
   /**
    * Answers the GeneLociI, or null if not known
@@ -562,7 +572,7 @@ public interface SequenceI extends ASequenceI
    *          the iterator to use
    * @return a String corresponding to the sequence
    */
-  public String getSequenceStringFromIterator(Iterator<int[]> it);
+  String getSequenceStringFromIterator(Iterator<int[]> it);
 
   /**
    * Locate the first position in this sequence which is not contained in an
@@ -572,5 +582,12 @@ public interface SequenceI extends ASequenceI
    *          iterator over regions
    * @return first residue not contained in regions
    */
-  public int firstResidueOutsideIterator(Iterator<int[]> it);
+  int firstResidueOutsideIterator(Iterator<int[]> it);
+
+  /**
+   * Answers true if this sequence has an associated Hidden Markov Model
+   * 
+   * @return
+   */
+  boolean hasHMMProfile();
 }
index 5d698c0..d52aa97 100644 (file)
@@ -62,6 +62,12 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.gui.ColourMenuHelper.ColourChangeListener;
 import jalview.gui.ViewSelectionMenu.ViewSetProvider;
+import jalview.hmmer.HMMAlign;
+import jalview.hmmer.HMMBuild;
+import jalview.hmmer.HMMERParamStore;
+import jalview.hmmer.HMMERPreset;
+import jalview.hmmer.HMMSearch;
+import jalview.hmmer.HmmerCommand;
 import jalview.io.AlignmentProperties;
 import jalview.io.AnnotationFile;
 import jalview.io.BioJsHTMLOutput;
@@ -88,6 +94,7 @@ import jalview.schemes.ColourSchemes;
 import jalview.schemes.ResidueColourScheme;
 import jalview.schemes.TCoffeeColourScheme;
 import jalview.util.MessageManager;
+import jalview.util.StringUtils;
 import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.ViewportRanges;
 import jalview.ws.DBRefFetcher;
@@ -95,6 +102,9 @@ import jalview.ws.DBRefFetcher.FetchFinishedListenerI;
 import jalview.ws.jws1.Discoverer;
 import jalview.ws.jws2.Jws2Discoverer;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.ParamDatastoreI;
+import jalview.ws.params.WsParamSetI;
 import jalview.ws.seqfetcher.DbSourceProxy;
 
 import java.awt.BorderLayout;
@@ -124,6 +134,7 @@ import java.awt.print.PrinterJob;
 import java.beans.PropertyChangeEvent;
 import java.io.File;
 import java.io.FileWriter;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.URL;
 import java.util.ArrayList;
@@ -132,14 +143,17 @@ import java.util.Deque;
 import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Scanner;
 import java.util.Vector;
 
 import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JEditorPane;
+import javax.swing.JFileChooser;
 import javax.swing.JInternalFrame;
 import javax.swing.JLayeredPane;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
 import javax.swing.JScrollPane;
 import javax.swing.SwingUtilities;
 
@@ -152,7 +166,6 @@ import javax.swing.SwingUtilities;
 public class AlignFrame extends GAlignFrame implements DropTargetListener,
         IProgressIndicator, AlignViewControllerGuiI, ColourChangeListener
 {
-
   public static final int DEFAULT_WIDTH = 700;
 
   public static final int DEFAULT_HEIGHT = 500;
@@ -178,6 +191,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    */
   String fileName = null;
 
+
   /**
    * Creates a new AlignFrame object with specific width and height.
    * 
@@ -762,6 +776,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       ap.av.updateConservation(ap);
       ap.av.updateConsensus(ap);
       ap.av.updateStrucConsensus(ap);
+      ap.av.initInformationWorker(ap);
     }
   }
 
@@ -904,6 +919,9 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     showConsensusHistogram.setSelected(av.isShowConsensusHistogram());
     showSequenceLogo.setSelected(av.isShowSequenceLogo());
     normaliseSequenceLogo.setSelected(av.isNormaliseSequenceLogo());
+    showInformationHistogram.setSelected(av.isShowInformationHistogram());
+    showHMMSequenceLogo.setSelected(av.isShowHMMSequenceLogo());
+    normaliseHMMSequenceLogo.setSelected(av.isNormaliseHMMSequenceLogo());
 
     ColourMenuHelper.setColourSelected(colourMenu,
             av.getGlobalColourScheme());
@@ -995,6 +1013,204 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
   }
 
   @Override
+  public void hmmBuild_actionPerformed(boolean withDefaults)
+  {
+    if (!alignmentIsSufficient(1))
+    {
+      return;
+    }
+
+    /*
+     * get default parameters, and optionally show a dialog
+     * to allow them to be modified
+     */
+    ParamDatastoreI store = HMMERParamStore.forBuild(viewport);
+    List<ArgumentI> args = store.getServiceParameters();
+
+    if (!withDefaults)
+    {
+      WsParamSetI set = new HMMERPreset();
+      WsJobParameters params = new WsJobParameters(store, set, args);
+      if (params.showRunDialog())
+      {
+        args = params.getJobParams();
+      }
+      else
+      {
+        return; // user cancelled
+      }
+    }
+    new Thread(new HMMBuild(this, args)).start();
+  }
+
+  @Override
+  public void hmmAlign_actionPerformed(boolean withDefaults)
+  {
+    if (!(checkForHMM() && alignmentIsSufficient(2)))
+    {
+      return;
+    }
+
+    /*
+     * get default parameters, and optionally show a dialog
+     * to allow them to be modified
+     */
+    ParamDatastoreI store = HMMERParamStore.forAlign(viewport);
+    List<ArgumentI> args = store.getServiceParameters();
+
+    if (!withDefaults)
+    {
+      WsParamSetI set = new HMMERPreset();
+      WsJobParameters params = new WsJobParameters(store, set, args);
+      if (params.showRunDialog())
+      {
+        args = params.getJobParams();
+      }
+      else
+      {
+        return; // user cancelled
+      }
+    }
+    new Thread(new HMMAlign(this, args)).start();
+  }
+
+  @Override
+  public void hmmSearch_actionPerformed(boolean withDefaults)
+  {
+    if (!checkForHMM())
+    {
+      return;
+    }
+
+    /*
+     * get default parameters, and (if requested) show 
+     * dialog to allow modification
+     */
+    ParamDatastoreI store = HMMERParamStore.forSearch(viewport);
+    List<ArgumentI> args = store.getServiceParameters();
+
+    if (!withDefaults)
+    {
+      WsParamSetI set = new HMMERPreset();
+      WsJobParameters params = new WsJobParameters(store, set, args);
+      if (params.showRunDialog())
+      {
+        args = params.getJobParams();
+      }
+      else
+      {
+        return; // user cancelled
+      }
+    }
+    new Thread(new HMMSearch(this, args)).start();
+    alignPanel.repaint();
+  }
+
+  /**
+   * Checks if the alignment has at least one hidden Markov model, if not shows
+   * a dialog advising to run hmmbuild or load an HMM profile
+   * 
+   * @return
+   */
+  private boolean checkForHMM()
+  {
+    if (viewport.getAlignment().getHmmSequences().isEmpty())
+    {
+      JOptionPane.showMessageDialog(this,
+              MessageManager.getString("warn.no_hmm"));
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Checks if the alignment contains the required number of sequences.
+   * 
+   * @param required
+   * @return
+   */
+  public boolean alignmentIsSufficient(int required)
+  {
+    if (getViewport().getAlignment().getSequences().size() < required)
+    {
+      JOptionPane.showMessageDialog(this,
+              MessageManager.getString("label.not_enough_sequences"));
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public void addDatabase_actionPerformed() throws IOException
+  {
+    if (Cache.getProperty(Preferences.HMMSEARCH_DB_PATHS) == null)
+    {
+      Cache.setProperty(Preferences.HMMSEARCH_DBS, "");
+      Cache.setProperty(Preferences.HMMSEARCH_DB_PATHS, "");
+    }
+
+    String path = openFileChooser(false);
+    if (path != null && new File(path).exists())
+    {
+      IdentifyFile identifier = new IdentifyFile();
+      FileFormatI format = identifier.identify(path, DataSourceType.FILE);
+      if (format == FileFormat.Fasta || format == FileFormat.Stockholm
+              || format == FileFormat.Pfam)
+      {
+        String currentDbs = Cache.getProperty(Preferences.HMMSEARCH_DBS);
+        String currentDbPaths = Cache
+                .getProperty(Preferences.HMMSEARCH_DB_PATHS);
+        currentDbPaths += " " + path;
+
+        String fileName = StringUtils.getLastToken(path, File.separator);
+        Scanner scanner = new Scanner(fileName).useDelimiter(".");
+        String name = scanner.next();
+        scanner.close();
+        currentDbs += " " + path; // TODO remove path from file name
+        scanner.close();
+
+        Cache.setProperty(Preferences.HMMSEARCH_DB_PATHS, currentDbPaths);
+        Cache.setProperty(Preferences.HMMSEARCH_DBS, currentDbPaths);
+      }
+      else
+      {
+        JOptionPane.showMessageDialog(this,
+                MessageManager.getString("warn.invalid_format"));
+      }
+    }
+  }
+
+  /**
+   * Opens a file chooser, optionally restricted to selecting folders
+   * (directories) only. Answers the path to the selected file or folder, or
+   * null if none is chosen.
+   * 
+   * @param
+   * @return
+   */
+  protected String openFileChooser(boolean forFolder)
+  {
+    // TODO duplicates GPreferences method - relocate to JalviewFileChooser?
+    String choice = null;
+    JFileChooser chooser = new JFileChooser();
+    if (forFolder)
+    {
+      chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+    }
+    chooser.setDialogTitle(
+            MessageManager.getString("label.open_local_file"));
+    chooser.setToolTipText(MessageManager.getString("action.open"));
+
+    int value = chooser.showOpenDialog(this);
+
+    if (value == JFileChooser.APPROVE_OPTION)
+    {
+      choice = chooser.getSelectedFile().getPath();
+    }
+    return choice;
+  }
+
+  @Override
   public void reload_actionPerformed(ActionEvent e)
   {
     if (fileName != null)
@@ -1403,6 +1619,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
 
   @Override
   public void associatedData_actionPerformed(ActionEvent e)
+          throws IOException, InterruptedException
   {
     // Pick the tree file
     JalviewFileChooser chooser = new JalviewFileChooser(
@@ -1888,9 +2105,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * 
    * @param e
    *          DOCUMENT ME!
+   * @throws InterruptedException
+   * @throws IOException
    */
   @Override
   protected void pasteNew_actionPerformed(ActionEvent e)
+          throws IOException, InterruptedException
   {
     paste(true);
   }
@@ -1900,9 +2120,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * 
    * @param e
    *          DOCUMENT ME!
+   * @throws InterruptedException
+   * @throws IOException
    */
   @Override
   protected void pasteThis_actionPerformed(ActionEvent e)
+          throws IOException, InterruptedException
   {
     paste(false);
   }
@@ -1912,8 +2135,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * 
    * @param newAlignment
    *          true to paste to a new alignment, otherwise add to this.
+   * @throws InterruptedException
+   * @throws IOException
    */
-  void paste(boolean newAlignment)
+  void paste(boolean newAlignment) throws IOException, InterruptedException
   {
     boolean externalPaste = true;
     try
@@ -2241,7 +2466,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       System.out.println("Exception whilst pasting: " + ex);
       // could be anything being pasted in here
     }
-
   }
 
   @Override
@@ -4541,6 +4765,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    * 
    * @param file
    *          either a filename or a URL string.
+   * @throws InterruptedException
+   * @throws IOException
    */
   public void loadJalviewDataFile(String file, DataSourceType sourceType,
           FileFormatI format, SequenceI assocSeq)
@@ -4647,7 +4873,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       }
       if (isAnnotation)
       {
-
         alignPanel.adjustAnnotationHeight();
         viewport.updateSequenceIdColours();
         buildSortByAnnotationScoresMenu();
@@ -5572,6 +5797,30 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
+  /**
+   * Sets the status of the HMMER menu
+   */
+  public void updateHMMERStatus()
+  {
+    hmmerMenu.setEnabled(HmmerCommand.isHmmerAvailable());
+  }
+
+  @Override
+  public void hmmerMenu_actionPerformed(ActionEvent e)
+  {
+    SequenceGroup grp = getViewport().getSelectionGroup();
+    if (grp != null)
+    {
+      hmmBuild.setText(MessageManager.getString("label.hmmbuild") + " from "
+              + grp.getName());
+    }
+    else
+    {
+      hmmBuild.setText(MessageManager.getString("label.hmmbuild")
+              + " from Alignment");
+    }
+  }
+
   @Override
   protected void loadVcf_actionPerformed()
   {
index 7e77bec..862c4fb 100644 (file)
@@ -92,6 +92,12 @@ public class AlignViewport extends AlignmentViewport
 
   private AnnotationColumnChooser annotationColumnSelectionState;
 
+  boolean validCharWidth;
+
+  public boolean followSelection = true;
+
+  private Hashtable<String, AutoCalcSetting> calcIdParams = new Hashtable<>();
+
   /**
    * Creates a new AlignViewport object.
    * 
@@ -254,14 +260,14 @@ public class AlignViewport extends AlignmentViewport
 
     setFont(new Font(fontName, style, Integer.parseInt(fontSize)), true);
 
-    alignment
-            .setGapCharacter(Cache.getDefault("GAP_SYMBOL", "-").charAt(0));
+    AlignmentI al = getAlignment();
+    al.setGapCharacter(Cache.getDefault("GAP_SYMBOL", "-").charAt(0));
 
     // We must set conservation and consensus before setting colour,
     // as Blosum and Clustal require this to be done
-    if (hconsensus == null && !isDataset)
+    if (consensusProfiles == null && !isDataset)
     {
-      if (!alignment.isNucleotide())
+      if (!al.isNucleotide())
       {
         showConservation = Cache.getDefault("SHOW_CONSERVATION", true);
         showQuality = Cache.getDefault("SHOW_QUALITY", true);
@@ -273,13 +279,19 @@ public class AlignViewport extends AlignmentViewport
       showSequenceLogo = Cache.getDefault("SHOW_CONSENSUS_LOGO", false);
       normaliseSequenceLogo = Cache.getDefault("NORMALISE_CONSENSUS_LOGO",
               false);
+      // for now, use consensus options for Information till it gets its own
+      setShowHMMSequenceLogo(showSequenceLogo);
+      setNormaliseHMMSequenceLogo(normaliseSequenceLogo);
+      setShowInformationHistogram(showConsensusHistogram);
       showGroupConsensus = Cache.getDefault("SHOW_GROUP_CONSENSUS", false);
       showConsensus = Cache.getDefault("SHOW_IDENTITY", true);
 
       showOccupancy = Cache.getDefault(Preferences.SHOW_OCCUPANCY, true);
     }
     initAutoAnnotation();
-    String colourProperty = alignment.isNucleotide()
+    // initInformation();
+
+    String colourProperty = al.isNucleotide()
             ? Preferences.DEFAULT_COLOUR_NUC
             : Preferences.DEFAULT_COLOUR_PROT;
     String schemeName = Cache.getProperty(colourProperty);
@@ -290,7 +302,7 @@ public class AlignViewport extends AlignmentViewport
               ResidueColourScheme.NONE);
     }
     ColourSchemeI colourScheme = ColourSchemeProperty
-            .getColourScheme(alignment, schemeName);
+            .getColourScheme(al, schemeName);
     residueShading = new ResidueShader(colourScheme);
 
     if (colourScheme instanceof UserColourScheme)
@@ -302,12 +314,10 @@ public class AlignViewport extends AlignmentViewport
 
     if (residueShading != null)
     {
-      residueShading.setConsensus(hconsensus);
+      residueShading.setConsensus(consensusProfiles);
     }
   }
 
-  boolean validCharWidth;
-
   /**
    * {@inheritDoc}
    */
@@ -390,9 +400,9 @@ public class AlignViewport extends AlignmentViewport
     /*
      * replace mappings on our alignment
      */
-    if (alignment != null && align != null)
+    if (getAlignment() != null && align != null)
     {
-      alignment.setCodonFrames(align.getCodonFrames());
+      getAlignment().setCodonFrames(align.getCodonFrames());
     }
   }
 
@@ -443,7 +453,7 @@ public class AlignViewport extends AlignmentViewport
   }
 
   /**
-   * returns the visible column regions of the alignment
+   * Returns an iterator over the visible column regions of the alignment
    * 
    * @param selectedRegionOnly
    *          true to just return the contigs intersecting with the selected
@@ -461,10 +471,11 @@ public class AlignViewport extends AlignmentViewport
     }
     else
     {
-      end = alignment.getWidth();
+      end = getAlignment().getWidth();
     }
-    return (alignment.getHiddenColumns().getVisContigsIterator(start, end,
-            false));
+
+    return getAlignment().getHiddenColumns().getVisContigsIterator(start,
+            end, false);
   }
 
   /**
@@ -513,8 +524,6 @@ public class AlignViewport extends AlignmentViewport
     return false;
   }
 
-  public boolean followSelection = true;
-
   /**
    * @return true if view selection should always follow the selections
    *         broadcast by other selection sources
@@ -580,17 +589,6 @@ public class AlignViewport extends AlignmentViewport
             .getStructureSelectionManager(Desktop.instance);
   }
 
-  @Override
-  public boolean isNormaliseSequenceLogo()
-  {
-    return normaliseSequenceLogo;
-  }
-
-  public void setNormaliseSequenceLogo(boolean state)
-  {
-    normaliseSequenceLogo = state;
-  }
-
   /**
    * 
    * @return true if alignment characters should be displayed
@@ -601,8 +599,6 @@ public class AlignViewport extends AlignmentViewport
     return validCharWidth;
   }
 
-  private Hashtable<String, AutoCalcSetting> calcIdParams = new Hashtable<>();
-
   public AutoCalcSetting getCalcIdSettingsFor(String calcId)
   {
     return calcIdParams.get(calcId);
@@ -1032,4 +1028,5 @@ public class AlignViewport extends AlignmentViewport
     }
     fr.setTransparency(featureSettings.getTransparency());
   }
+
 }
index 6f8b225..b1a8aff 100755 (executable)
@@ -34,6 +34,7 @@ import jalview.io.FormatAdapter;
 import jalview.util.Comparison;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
+import jalview.workers.InformationThread;
 
 import java.awt.Color;
 import java.awt.Cursor;
@@ -51,8 +52,6 @@ import java.awt.event.MouseEvent;
 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;
@@ -354,6 +353,10 @@ public class AnnotationLabels extends JPanel
       pop.show(this, evt.getX(), evt.getY());
       return;
     }
+
+    final AlignmentAnnotation ann = aa[selectedRow];
+    final boolean isSequenceAnnotation = ann.sequenceRef != null;
+
     item = new JMenuItem(EDITNAME);
     item.addActionListener(this);
     pop.add(item);
@@ -363,9 +366,9 @@ public class AnnotationLabels extends JPanel
     // JAL-1264 hide all sequence-specific annotations of this type
     if (selectedRow < aa.length)
     {
-      if (aa[selectedRow].sequenceRef != null)
+      if (isSequenceAnnotation)
       {
-        final String label = aa[selectedRow].label;
+        final String label = ann.label;
         JMenuItem hideType = new JMenuItem();
         String text = MessageManager.getString("label.hide_all") + " "
                 + label;
@@ -378,15 +381,6 @@ public class AnnotationLabels extends JPanel
             AlignmentUtils.showOrHideSequenceAnnotations(
                     ap.av.getAlignment(), Collections.singleton(label),
                     null, false, false);
-            // for (AlignmentAnnotation ann : ap.av.getAlignment()
-            // .getAlignmentAnnotation())
-            // {
-            // if (ann.sequenceRef != null && ann.label != null
-            // && ann.label.equals(label))
-            // {
-            // ann.visible = false;
-            // }
-            // }
             ap.refresh(true);
           }
         });
@@ -409,190 +403,317 @@ public class AnnotationLabels extends JPanel
     // property methods
     if (selectedRow < aa.length)
     {
-      final String label = aa[selectedRow].label;
-      if (!aa[selectedRow].autoCalculated)
+      final String label = ann.label;
+      if (!(ann.autoCalculated)
+              && !(InformationThread.HMM_CALC_ID.equals(ann.getCalcId())))
       {
-        if (aa[selectedRow].graph == AlignmentAnnotation.NO_GRAPH)
+        if (ann.graph == AlignmentAnnotation.NO_GRAPH)
         {
           // display formatting settings for this row.
           pop.addSeparator();
           // av and sequencegroup need to implement same interface for
           item = new JCheckBoxMenuItem(TOGGLE_LABELSCALE,
-                  aa[selectedRow].scaleColLabel);
+                  ann.scaleColLabel);
           item.addActionListener(this);
           pop.add(item);
         }
       }
       else if (label.indexOf("Consensus") > -1)
       {
-        pop.addSeparator();
-        // av and sequencegroup need to implement same interface for
-        final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(
-                MessageManager.getString("label.ignore_gaps_consensus"),
-                (aa[selectedRow].groupRef != null)
-                        ? aa[selectedRow].groupRef.getIgnoreGapsConsensus()
-                        : ap.av.isIgnoreGapsConsensus());
-        final AlignmentAnnotation aaa = aa[selectedRow];
-        cbmi.addActionListener(new ActionListener()
+        addConsensusMenu(pop, ann);
+      }
+      else if (InformationThread.HMM_CALC_ID.equals(ann.getCalcId()))
+      {
+        addHmmerMenu(pop, ann);
+      }
+    }
+    pop.show(this, evt.getX(), evt.getY());
+  }
+
+  /**
+   * Adds context menu options for (alignment or group) Hmmer annotation
+   * 
+   * @param pop
+   * @param ann
+   */
+  protected void addHmmerMenu(JPopupMenu pop, final AlignmentAnnotation ann)
+  {
+    final boolean isGroupAnnotation = ann.groupRef != null;
+    pop.addSeparator();
+    final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(
+            MessageManager.getString(
+                    "label.ignore_below_background_frequency"),
+            isGroupAnnotation
+                    ? ann.groupRef
+                            .isIgnoreBelowBackground()
+                    : ap.av.isIgnoreBelowBackground());
+    cbmi.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        if (isGroupAnnotation)
         {
-          @Override
-          public void actionPerformed(ActionEvent e)
+          if (!ann.groupRef.isUseInfoLetterHeight())
           {
-            if (aaa.groupRef != null)
-            {
-              // TODO: pass on reference to ap so the view can be updated.
-              aaa.groupRef.setIgnoreGapsConsensus(cbmi.getState());
-              ap.getAnnotationPanel()
-                      .paint(ap.getAnnotationPanel().getGraphics());
-            }
-            else
-            {
-              ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
-            }
-            ap.alignmentChanged();
+            ann.groupRef.setIgnoreBelowBackground(cbmi.getState());
+            // todo and recompute group annotation
           }
-        });
-        pop.add(cbmi);
-        // av and sequencegroup need to implement same interface for
-        if (aaa.groupRef != null)
+        }
+        else if (!ap.av.isInfoLetterHeight())
         {
-          final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
-                  MessageManager.getString("label.show_group_histogram"),
-                  aa[selectedRow].groupRef.isShowConsensusHistogram());
-          chist.addActionListener(new ActionListener()
-          {
-            @Override
-            public void actionPerformed(ActionEvent e)
-            {
-              // TODO: pass on reference
-              // to ap
-              // so the
-              // view
-              // can be
-              // updated.
-              aaa.groupRef.setShowConsensusHistogram(chist.getState());
-              ap.repaint();
-              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
-            }
-          });
-          pop.add(chist);
-          final JCheckBoxMenuItem cprofl = new JCheckBoxMenuItem(
-                  MessageManager.getString("label.show_group_logo"),
-                  aa[selectedRow].groupRef.isShowSequenceLogo());
-          cprofl.addActionListener(new ActionListener()
-          {
-            @Override
-            public void actionPerformed(ActionEvent e)
-            {
-              // TODO: pass on reference
-              // to ap
-              // so the
-              // view
-              // can be
-              // updated.
-              aaa.groupRef.setshowSequenceLogo(cprofl.getState());
-              ap.repaint();
-              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
-            }
-          });
-          pop.add(cprofl);
-          final JCheckBoxMenuItem cproflnorm = new JCheckBoxMenuItem(
-                  MessageManager.getString("label.normalise_group_logo"),
-                  aa[selectedRow].groupRef.isNormaliseSequenceLogo());
-          cproflnorm.addActionListener(new ActionListener()
-          {
-            @Override
-            public void actionPerformed(ActionEvent e)
-            {
+          ap.av.setIgnoreBelowBackground(cbmi.getState(), ap);
+          // todo and recompute annotation
+        }
+        ap.alignmentChanged(); // todo not like this
+      }
+    });
+    pop.add(cbmi);
+    final JCheckBoxMenuItem letterHeight = new JCheckBoxMenuItem(
+            MessageManager.getString("label.use_info_for_height"),
+            isGroupAnnotation ? ann.groupRef.isUseInfoLetterHeight()
+                    : ap.av.isInfoLetterHeight());
+    letterHeight.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        if (isGroupAnnotation)
+        {
+          ann.groupRef.setInfoLetterHeight((letterHeight.getState()));
+          ann.groupRef.setIgnoreBelowBackground(true);
+          // todo and recompute group annotation
+        }
+        else
+        {
+          ap.av.setInfoLetterHeight(letterHeight.getState(), ap);
+          ap.av.setIgnoreBelowBackground(true, ap);
+          // todo and recompute annotation
+        }
+        ap.alignmentChanged();
+      }
+    });
+    pop.add(letterHeight);
+    if (isGroupAnnotation)
+    {
+      final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
+              MessageManager.getString("label.show_group_histogram"),
+              ann.groupRef.isShowInformationHistogram());
+      chist.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          ann.groupRef.setShowInformationHistogram(chist.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(chist);
+      final JCheckBoxMenuItem cprofl = new JCheckBoxMenuItem(
+              MessageManager.getString("label.show_group_logo"),
+              ann.groupRef.isShowHMMSequenceLogo());
+      cprofl.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          ann.groupRef.setShowHMMSequenceLogo(cprofl.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(cprofl);
+      final JCheckBoxMenuItem cproflnorm = new JCheckBoxMenuItem(
+              MessageManager.getString("label.normalise_group_logo"),
+              ann.groupRef.isNormaliseHMMSequenceLogo());
+      cproflnorm.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          ann.groupRef
+                  .setNormaliseHMMSequenceLogo(cproflnorm.getState());
+          // automatically enable logo display if we're clicked
+          ann.groupRef.setShowHMMSequenceLogo(true);
+          ap.repaint();
+        }
+      });
+      pop.add(cproflnorm);
+    }
+    else
+    {
+      final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
+              MessageManager.getString("label.show_histogram"),
+              av.isShowInformationHistogram());
+      chist.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          av.setShowInformationHistogram(chist.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(chist);
+      final JCheckBoxMenuItem cprof = new JCheckBoxMenuItem(
+              MessageManager.getString("label.show_logo"),
+              av.isShowHMMSequenceLogo());
+      cprof.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          av.setShowHMMSequenceLogo(cprof.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(cprof);
+      final JCheckBoxMenuItem cprofnorm = new JCheckBoxMenuItem(
+              MessageManager.getString("label.normalise_logo"),
+              av.isNormaliseHMMSequenceLogo());
+      cprofnorm.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          av.setShowHMMSequenceLogo(true);
+          av.setNormaliseHMMSequenceLogo(cprofnorm.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(cprofnorm);
+    }
+  }
 
-              // TODO: pass on reference
-              // to ap
-              // so the
-              // view
-              // can be
-              // updated.
-              aaa.groupRef.setNormaliseSequenceLogo(cproflnorm.getState());
-              // automatically enable logo display if we're clicked
-              aaa.groupRef.setshowSequenceLogo(true);
-              ap.repaint();
-              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
-            }
-          });
-          pop.add(cproflnorm);
+  /**
+   * Adds context menu options for (alignment or group) Consensus annotation
+   * 
+   * @param pop
+   * @param ann
+   */
+  protected void addConsensusMenu(JPopupMenu pop,
+          final AlignmentAnnotation ann)
+  {
+    final boolean isGroupAnnotation = ann.groupRef != null;
+    pop.addSeparator();
+
+    final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(
+            MessageManager.getString("label.ignore_gaps_consensus"),
+            (ann.groupRef != null)
+                    ? ann.groupRef.isIgnoreGapsConsensus()
+                    : ap.av.isIgnoreGapsConsensus());
+    cbmi.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        if (isGroupAnnotation)
+        {
+          ann.groupRef.setIgnoreGapsConsensus(cbmi.getState());
         }
         else
         {
-          final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
-                  MessageManager.getString("label.show_histogram"),
-                  av.isShowConsensusHistogram());
-          chist.addActionListener(new ActionListener()
-          {
-            @Override
-            public void actionPerformed(ActionEvent e)
-            {
-              // TODO: pass on reference
-              // to ap
-              // so the
-              // view
-              // can be
-              // updated.
-              av.setShowConsensusHistogram(chist.getState());
-              ap.alignFrame.setMenusForViewport();
-              ap.repaint();
-              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
-            }
-          });
-          pop.add(chist);
-          final JCheckBoxMenuItem cprof = new JCheckBoxMenuItem(
-                  MessageManager.getString("label.show_logo"),
-                  av.isShowSequenceLogo());
-          cprof.addActionListener(new ActionListener()
-          {
-            @Override
-            public void actionPerformed(ActionEvent e)
-            {
-              // TODO: pass on reference
-              // to ap
-              // so the
-              // view
-              // can be
-              // updated.
-              av.setShowSequenceLogo(cprof.getState());
-              ap.alignFrame.setMenusForViewport();
-              ap.repaint();
-              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
-            }
-          });
-          pop.add(cprof);
-          final JCheckBoxMenuItem cprofnorm = new JCheckBoxMenuItem(
-                  MessageManager.getString("label.normalise_logo"),
-                  av.isNormaliseSequenceLogo());
-          cprofnorm.addActionListener(new ActionListener()
-          {
-            @Override
-            public void actionPerformed(ActionEvent e)
-            {
-              // TODO: pass on reference
-              // to ap
-              // so the
-              // view
-              // can be
-              // updated.
-              av.setShowSequenceLogo(true);
-              av.setNormaliseSequenceLogo(cprofnorm.getState());
-              ap.alignFrame.setMenusForViewport();
-              ap.repaint();
-              // ap.annotationPanel.paint(ap.annotationPanel.getGraphics());
-            }
-          });
-          pop.add(cprofnorm);
+          ap.av.setIgnoreGapsConsensus(cbmi.getState(), ap);
         }
-        final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ);
-        consclipbrd.addActionListener(this);
-        pop.add(consclipbrd);
+        ap.alignmentChanged();
       }
+    });
+    pop.add(cbmi);
+    if (isGroupAnnotation)
+    {
+      /*
+       * group consensus options
+       */
+      final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
+              MessageManager.getString("label.show_group_histogram"),
+              ann.groupRef.isShowConsensusHistogram());
+      chist.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          ann.groupRef.setShowConsensusHistogram(chist.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(chist);
+      final JCheckBoxMenuItem cprofl = new JCheckBoxMenuItem(
+              MessageManager.getString("label.show_group_logo"),
+              ann.groupRef.isShowSequenceLogo());
+      cprofl.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          ann.groupRef.setshowSequenceLogo(cprofl.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(cprofl);
+      final JCheckBoxMenuItem cproflnorm = new JCheckBoxMenuItem(
+              MessageManager.getString("label.normalise_group_logo"),
+              ann.groupRef.isNormaliseSequenceLogo());
+      cproflnorm.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          ann.groupRef.setNormaliseSequenceLogo(cproflnorm.getState());
+          // automatically enable logo display if we're clicked
+          ann.groupRef.setshowSequenceLogo(true);
+          ap.repaint();
+        }
+      });
+      pop.add(cproflnorm);
     }
-    pop.show(this, evt.getX(), evt.getY());
+    else
+    {
+      /*
+       * alignment consensus options
+       */
+      final JCheckBoxMenuItem chist = new JCheckBoxMenuItem(
+              MessageManager.getString("label.show_histogram"),
+              av.isShowConsensusHistogram());
+      chist.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          av.setShowConsensusHistogram(chist.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(chist);
+      final JCheckBoxMenuItem cprof = new JCheckBoxMenuItem(
+              MessageManager.getString("label.show_logo"),
+              av.isShowSequenceLogo());
+      cprof.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          av.setShowSequenceLogo(cprof.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(cprof);
+      final JCheckBoxMenuItem cprofnorm = new JCheckBoxMenuItem(
+              MessageManager.getString("label.normalise_logo"),
+              av.isNormaliseSequenceLogo());
+      cprofnorm.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          av.setShowSequenceLogo(true);
+          av.setNormaliseSequenceLogo(cprofnorm.getState());
+          ap.repaint();
+        }
+      });
+      pop.add(cprofnorm);
+    }
+    final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ);
+    consclipbrd.addActionListener(this);
+    pop.add(consclipbrd);
   }
 
   /**
@@ -906,7 +1027,6 @@ public class AnnotationLabels extends JPanel
             PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
             ap.av.sendSelection();
           }
-
         }
       }
       return;
@@ -978,7 +1098,6 @@ public class AnnotationLabels extends JPanel
   @Override
   public void paintComponent(Graphics g)
   {
-
     int width = getWidth();
     if (width == 0)
     {
@@ -993,7 +1112,6 @@ public class AnnotationLabels extends JPanel
     }
 
     drawComponent(g2, true, width);
-
   }
 
   /**
index f674c7e..eaaf0a5 100644 (file)
@@ -23,10 +23,12 @@ package jalview.gui;
 import jalview.analysis.TreeBuilder;
 import jalview.analysis.scoremodels.ScoreModels;
 import jalview.analysis.scoremodels.SimilarityParams;
+import jalview.api.AlignViewportI;
 import jalview.api.analysis.ScoreModelI;
 import jalview.api.analysis.SimilarityParamsI;
 import jalview.datamodel.SequenceGroup;
 import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -103,7 +105,7 @@ public class CalculationChooser extends JPanel
 
   final ComboBoxTooltipRenderer renderer = new ComboBoxTooltipRenderer();
 
-  List<String> tips = new ArrayList<String>();
+  List<String> tips = new ArrayList<>();
 
   /*
    * the most recently opened PCA results panel
@@ -375,7 +377,7 @@ public class CalculationChooser extends JPanel
    */
   protected JComboBox<String> buildModelOptionsList()
   {
-    final JComboBox<String> scoreModelsCombo = new JComboBox<String>();
+    final JComboBox<String> scoreModelsCombo = new JComboBox<>();
     scoreModelsCombo.setRenderer(renderer);
 
     /*
@@ -418,7 +420,7 @@ public class CalculationChooser extends JPanel
   {
     Object curSel = comboBox.getSelectedItem();
     toolTips.clear();
-    DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>();
+    DefaultComboBoxModel<String> model = new DefaultComboBoxModel<>();
 
     /*
      * now we can actually add entries to the combobox,
@@ -492,7 +494,7 @@ public class CalculationChooser extends JPanel
      * gui validation shouldn't allow insufficient sequences here, but leave
      * this check in in case this method gets exposed programmatically in future
      */
-    AlignViewport viewport = af.getViewport();
+    AlignViewportI viewport = af.getViewport();
     SequenceGroup sg = viewport.getSelectionGroup();
     if (sg != null && sg.getSize() < MIN_TREE_SELECTION)
     {
@@ -519,7 +521,7 @@ public class CalculationChooser extends JPanel
    */
   protected void openPcaPanel(String modelName, SimilarityParamsI params)
   {
-    AlignViewport viewport = af.getViewport();
+    AlignViewportI viewport = af.getViewport();
 
     /*
      * gui validation shouldn't allow insufficient sequences here, but leave
index 8f0b88c..9479ea6 100644 (file)
@@ -121,8 +121,7 @@ public class ColourMenuHelper
        */
       final String name = scheme.getSchemeName();
       String label = MessageManager.getStringOrReturn(
-              "label.colourScheme_" + name.toLowerCase().replace(" ", "_"),
-              name);
+              "label.colourScheme_", name.toLowerCase().replace(" ", "_"));
       final JRadioButtonMenuItem radioItem = new JRadioButtonMenuItem(
               label);
       radioItem.setName(name);
index 75033f3..be64c85 100644 (file)
@@ -1471,7 +1471,8 @@ public class Desktop extends jalview.jbgui.GDesktop
       return;
     }
 
-    AlignmentViewport source = null, target = null;
+    AlignViewportI source = null;
+    AlignViewportI target = null;
     if (frames[0] instanceof AlignFrame)
     {
       source = ((AlignFrame) frames[0]).getCurrentView();
index 9285754..aed73d6 100644 (file)
@@ -30,6 +30,7 @@ import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.GraphLine;
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.RnaViewerModel;
 import jalview.datamodel.SequenceFeature;
@@ -45,6 +46,7 @@ import jalview.ext.varna.RnaModel;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
+import jalview.io.HMMFile;
 import jalview.renderer.ResidueShaderI;
 import jalview.schemabinding.version2.AlcodMap;
 import jalview.schemabinding.version2.AlcodonFrame;
@@ -52,7 +54,6 @@ import jalview.schemabinding.version2.Annotation;
 import jalview.schemabinding.version2.AnnotationColours;
 import jalview.schemabinding.version2.AnnotationElement;
 import jalview.schemabinding.version2.CalcIdParam;
-import jalview.schemabinding.version2.Colour;
 import jalview.schemabinding.version2.CompoundMatcher;
 import jalview.schemabinding.version2.DBRef;
 import jalview.schemabinding.version2.Features;
@@ -167,6 +168,8 @@ public class Jalview2XML
 
   private static final String RNA_PREFIX = "rna_";
 
+  private static final String HMMER_PREFIX = "hmmer_";
+
   private static final String UTF_8 = "UTF-8";
 
   // use this with nextCounter() to make unique names for entities
@@ -867,73 +870,28 @@ public class Jalview2XML
         }
       }
 
-      // TODO: omit sequence features from each alignment view's XML dump if we
-      // are storing dataset
-      List<jalview.datamodel.SequenceFeature> sfs = jds
-              .getSequenceFeatures();
+      /*
+       * save sequence features
+       * TODO: omit sequence features from each alignment view's 
+       * XML dump if we are storing dataset
+       */
+      List<SequenceFeature> sfs = jds.getSequenceFeatures();
       for (SequenceFeature sf : sfs)
       {
-        Features features = new Features();
-
-        features.setBegin(sf.getBegin());
-        features.setEnd(sf.getEnd());
-        features.setDescription(sf.getDescription());
-        features.setType(sf.getType());
-        features.setFeatureGroup(sf.getFeatureGroup());
-        features.setScore(sf.getScore());
-        if (sf.links != null)
-        {
-          for (int l = 0; l < sf.links.size(); l++)
-          {
-            OtherData keyValue = new OtherData();
-            keyValue.setKey("LINK_" + l);
-            keyValue.setValue(sf.links.elementAt(l).toString());
-            features.addOtherData(keyValue);
-          }
-        }
-        if (sf.otherDetails != null)
-        {
-          /*
-           * save feature attributes, which may be simple strings or
-           * map valued (have sub-attributes)
-           */
-          for (Entry<String, Object> entry : sf.otherDetails.entrySet())
-          {
-            String key = entry.getKey();
-            Object value = entry.getValue();
-            if (value instanceof Map<?, ?>)
-            {
-              for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
-                      .entrySet())
-              {
-                OtherData otherData = new OtherData();
-                otherData.setKey(key);
-                otherData.setKey2(subAttribute.getKey());
-                otherData.setValue(subAttribute.getValue().toString());
-                features.addOtherData(otherData);
-              }
-            }
-            else
-            {
-              OtherData otherData = new OtherData();
-              otherData.setKey(key);
-              otherData.setValue(value.toString());
-              features.addOtherData(otherData);
-            }
-          }
-        }
-
+        Features features = saveFeature(sf);
         jseq.addFeatures(features);
       }
 
+      /*
+       * save PDB entries for sequence
+       */
       if (jdatasq.getAllPDBEntries() != null)
       {
-        Enumeration en = jdatasq.getAllPDBEntries().elements();
+        Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
         while (en.hasMoreElements())
         {
           Pdbids pdb = new Pdbids();
-          jalview.datamodel.PDBEntry entry = (jalview.datamodel.PDBEntry) en
-                  .nextElement();
+          PDBEntry entry = en.nextElement();
 
           String pdbId = entry.getId();
           pdb.setId(pdbId);
@@ -1017,6 +975,11 @@ public class Jalview2XML
 
       saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
 
+      if (jds.hasHMMProfile())
+      {
+        saveHmmerProfile(jout, jseq, jds);
+      }
+
       jms.addJSeq(jseq);
     }
 
@@ -1223,7 +1186,7 @@ public class Jalview2XML
         jGroup.setTextCol2(sg.textColour2.getRGB());
         jGroup.setTextColThreshold(sg.thresholdTextColour);
         jGroup.setShowUnconserved(sg.getShowNonconserved());
-        jGroup.setIgnoreGapsinConsensus(sg.getIgnoreGapsConsensus());
+        jGroup.setIgnoreGapsinConsensus(sg.isIgnoreGapsConsensus());
         jGroup.setShowConsensusHistogram(sg.isShowConsensusHistogram());
         jGroup.setShowSequenceLogo(sg.isShowSequenceLogo());
         jGroup.setNormaliseSequenceLogo(sg.isNormaliseSequenceLogo());
@@ -1508,6 +1471,98 @@ public class Jalview2XML
   }
 
   /**
+   * Saves the HMMER profile associated with the sequence as a file in the jar,
+   * in HMMER format, and saves the name of the file as a child element of the
+   * XML sequence element
+   * 
+   * @param jout
+   * @param xmlSeq
+   * @param seq
+   */
+  protected void saveHmmerProfile(JarOutputStream jout, JSeq xmlSeq,
+          SequenceI seq)
+  {
+    HiddenMarkovModel profile = seq.getHMM();
+    if (profile == null)
+    {
+      warn("Want to save HMM profile for " + seq.getName()
+              + " but none found");
+      return;
+    }
+    HMMFile hmmFile = new HMMFile(profile);
+    String hmmAsString = hmmFile.print();
+    String jarEntryName = HMMER_PREFIX + nextCounter();
+    try
+    {
+      writeJarEntry(jout, jarEntryName, hmmAsString.getBytes());
+      xmlSeq.setHmmerProfile(jarEntryName);
+    } catch (IOException e)
+    {
+      warn("Error saving HMM profile: " + e.getMessage());
+    }
+  }
+
+  /**
+   * Converts a Jalview SequenceFeature into the XML model of it to save
+   * 
+   * @param sf
+   * @return
+   */
+  protected Features saveFeature(SequenceFeature sf)
+  {
+    Features features = new Features();
+
+    features.setBegin(sf.getBegin());
+    features.setEnd(sf.getEnd());
+    features.setDescription(sf.getDescription());
+    features.setType(sf.getType());
+    features.setFeatureGroup(sf.getFeatureGroup());
+    features.setScore(sf.getScore());
+    if (sf.links != null)
+    {
+      for (int l = 0; l < sf.links.size(); l++)
+      {
+        OtherData keyValue = new OtherData();
+        keyValue.setKey("LINK_" + l);
+        keyValue.setValue(sf.links.elementAt(l).toString());
+        features.addOtherData(keyValue);
+      }
+    }
+    if (sf.otherDetails != null)
+    {
+      /*
+       * save feature attributes, which may be simple strings or
+       * map valued (have sub-attributes)
+       */
+      for (Entry<String, Object> entry : sf.otherDetails.entrySet())
+      {
+        String key = entry.getKey();
+        Object value = entry.getValue();
+        if (value instanceof Map<?, ?>)
+        {
+          for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
+                  .entrySet())
+          {
+            OtherData otherData = new OtherData();
+            otherData.setKey(key);
+            otherData.setKey2(subAttribute.getKey());
+            otherData.setValue(subAttribute.getValue().toString());
+            features.addOtherData(otherData);
+          }
+        }
+        else
+        {
+          OtherData otherData = new OtherData();
+          otherData.setKey(key);
+          otherData.setValue(value.toString());
+          features.addOtherData(otherData);
+        }
+      }
+    }
+    return features;
+  }
+
+  /**
    * Save any Varna viewers linked to this sequence. Writes an rnaViewer element
    * for each viewer, with
    * <ul>
@@ -1708,9 +1763,8 @@ public class Jalview2XML
       }
       else if (!matchedFile.equals(pdbentry.getFile()))
       {
-        Cache.log.warn(
-                "Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
-                        + pdbentry.getFile());
+        warn("Probably lost some PDB-Sequence mappings for this structure file (which apparently has same PDB Entry code): "
+                + pdbentry.getFile());
       }
       // record the
       // file so we
@@ -2194,12 +2248,12 @@ public class Jalview2XML
         mpc.setDseqFor(jmpid);
         if (!seqRefIds.containsKey(mpc.getDseqFor()))
         {
-          jalview.bin.Cache.log.debug("creatign new DseqFor ID");
+          debug("creating new DseqFor ID");
           seqRefIds.put(mpc.getDseqFor(), ps);
         }
         else
         {
-          jalview.bin.Cache.log.debug("reusing DseqFor ID");
+          debug("reusing DseqFor ID");
         }
 
         mp.setMappingChoice(mpc);
@@ -3014,24 +3068,26 @@ public class Jalview2XML
       //
       for (int i = 0; i < vamsasSeq.length; i++)
       {
+        SequenceI alignmentSeq = al.getSequenceAt(i);
         if (jseqs[i].getFeaturesCount() > 0)
         {
           Features[] features = jseqs[i].getFeatures();
           for (int f = 0; f < features.length; f++)
           {
-            SequenceFeature sf = new SequenceFeature(features[f].getType(),
-                    features[f].getDescription(), features[f].getBegin(),
-                    features[f].getEnd(), features[f].getScore(),
-                    features[f].getFeatureGroup());
-            sf.setStatus(features[f].getStatus());
+            Features feature = features[f];
+            SequenceFeature sf = new SequenceFeature(feature.getType(),
+                    feature.getDescription(), feature.getBegin(),
+                    feature.getEnd(), feature.getScore(),
+                    feature.getFeatureGroup());
+            sf.setStatus(feature.getStatus());
 
             /*
              * load any feature attributes - include map-valued attributes
              */
             Map<String, Map<String, String>> mapAttributes = new HashMap<>();
-            for (int od = 0; od < features[f].getOtherDataCount(); od++)
+            for (int od = 0; od < feature.getOtherDataCount(); od++)
             {
-              OtherData keyValue = features[f].getOtherData(od);
+              OtherData keyValue = feature.getOtherData(od);
               String attributeName = keyValue.getKey();
               String attributeValue = keyValue.getValue();
               if (attributeName.startsWith("LINK"))
@@ -3065,16 +3121,15 @@ public class Jalview2XML
             }
 
             // adds feature to datasequence's feature set (since Jalview 2.10)
-            al.getSequenceAt(i).addSequenceFeature(sf);
+            alignmentSeq.addSequenceFeature(sf);
           }
         }
         if (vamsasSeq[i].getDBRefCount() > 0)
         {
           // adds dbrefs to datasequence's set (since Jalview 2.10)
           addDBRefs(
-                  al.getSequenceAt(i).getDatasetSequence() == null
-                          ? al.getSequenceAt(i)
-                          : al.getSequenceAt(i).getDatasetSequence(),
+                  alignmentSeq.getDatasetSequence() == null ? alignmentSeq
+                          : alignmentSeq.getDatasetSequence(),
                   vamsasSeq[i]);
         }
         if (jseqs[i].getPdbidsCount() > 0)
@@ -3122,16 +3177,25 @@ public class Jalview2XML
                     .getStructureSelectionManager(Desktop.instance)
                     .registerPDBEntry(entry);
             // adds PDBEntry to datasequence's set (since Jalview 2.10)
-            if (al.getSequenceAt(i).getDatasetSequence() != null)
+            if (alignmentSeq.getDatasetSequence() != null)
             {
-              al.getSequenceAt(i).getDatasetSequence().addPDBId(entry);
+              alignmentSeq.getDatasetSequence().addPDBId(entry);
             }
             else
             {
-              al.getSequenceAt(i).addPDBId(entry);
+              alignmentSeq.addPDBId(entry);
             }
           }
         }
+
+        /*
+         * load any HMMER profile
+         */
+        String hmmJarFile = jseqs[i].getHmmerProfile();
+        if (hmmJarFile != null)
+        {
+          loadHmmerProfile(jprovider, hmmJarFile, alignmentSeq);
+        }
       }
     } // end !multipleview
 
@@ -3629,6 +3693,31 @@ public class Jalview2XML
   }
 
   /**
+   * Loads a HMMER profile from a file stored in the project, and associates it
+   * with the specified sequence
+   * 
+   * @param jprovider
+   * @param hmmJarFile
+   * @param seq
+   */
+  protected void loadHmmerProfile(jarInputStreamProvider jprovider,
+          String hmmJarFile, SequenceI seq)
+  {
+    try
+    {
+      String hmmFile = copyJarEntry(jprovider, hmmJarFile, "hmm", null);
+      HMMFile parser = new HMMFile(hmmFile, DataSourceType.FILE);
+      HiddenMarkovModel hmmModel = parser.getHMM();
+      hmmModel = new HiddenMarkovModel(hmmModel, seq);
+      seq.setHMM(hmmModel);
+    } catch (IOException e)
+    {
+      warn("Error loading HMM profile for " + seq.getName() + ": "
+              + e.getMessage());
+    }
+  }
+
+  /**
    * Instantiate and link any saved RNA (Varna) viewers. The state of the Varna
    * panel is restored from separate jar entries, two (gapped and trimmed) per
    * sequence and secondary structure.
@@ -4561,7 +4650,7 @@ public class Jalview2XML
     af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
             view.getIgnoreGapsinConsensus());
     af.viewport.getResidueShading()
-            .setConsensus(af.viewport.getSequenceConsensusHash());
+            .setConsensus(af.viewport.getConsensusProfiles());
     af.viewport.setColourAppliesToAllGroups(false);
 
     if (view.getConservationSelected() && cs != null)
@@ -5055,10 +5144,7 @@ public class Jalview2XML
             id = object.getJalviewModelSequence().getViewport()[0]
                     .getSequenceSetId()))
     {
-      if (Cache.log != null && Cache.log.isDebugEnabled())
-      {
-        Cache.log.debug("Skipping seuqence set id " + id);
-      }
+      debug("Skipping sequence set id " + id);
       return true;
     }
     return false;
@@ -5432,7 +5518,7 @@ public class Jalview2XML
           seqRefIds.put(sqid, djs);
 
         }
-        jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
+        debug("about to recurse on addDBRefs.");
         addDBRefs(djs, ms);
 
       }
@@ -5610,7 +5696,7 @@ public class Jalview2XML
       }
       else
       {
-        Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
+        debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
       }
     }
   }
@@ -5942,7 +6028,10 @@ public class Jalview2XML
         maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
       } catch (Exception e)
       {
-        Cache.log.warn("Couldn't parse out graduated feature color.", e);
+        if (Cache.log != null)
+        {
+          Cache.log.warn("Couldn't parse out graduated feature color.", e);
+        }
       }
   
       NoValueColour noCol = colourModel.getNoValueColour();
index 331e738..5cbf228 100755 (executable)
@@ -413,7 +413,7 @@ public class Jalview2XML_V1
     af.viewport.getResidueShading().setThreshold(view.getPidThreshold(),
             true);
     af.viewport.getResidueShading()
-            .setConsensus(af.viewport.getSequenceConsensusHash());
+            .setConsensus(af.viewport.getConsensusProfiles());
     af.viewport.setColourAppliesToAllGroups(false);
     af.alignPanel.updateLayout();
     af.changeColour(cs);
index 4658668..190eda1 100644 (file)
@@ -22,12 +22,10 @@ package jalview.gui;
 
 import jalview.util.MessageManager;
 
-import java.awt.BorderLayout;
 import java.awt.Color;
 import java.awt.Component;
+import java.awt.Container;
 import java.awt.Font;
-import java.awt.GridLayout;
-import java.awt.Rectangle;
 import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
@@ -39,10 +37,8 @@ import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JComboBox;
 import javax.swing.JComponent;
-import javax.swing.JLabel;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
-import javax.swing.JPanel;
 import javax.swing.JScrollBar;
 import javax.swing.SwingConstants;
 import javax.swing.border.Border;
@@ -144,54 +140,23 @@ public final class JvSwingUtils
   }
 
   /**
+   * A convenience method that that adds a component with label to a container,
+   * sets a tooltip on both component and label, and optionally specifies layout
+   * constraints for the added component (but not the label)
    * 
-   * @param panel
+   * @param container
    * @param tooltip
    * @param label
-   * @param valBox
-   * @return the GUI element created that was added to the layout so it's
-   *         attributes can be changed.
+   * @param comp
+   * @param constraints
    */
-  public static JPanel addtoLayout(JPanel panel, String tooltip,
-          JComponent label, JComponent valBox)
-  {
-    JPanel laypanel = new JPanel(new GridLayout(1, 2));
-    JPanel labPanel = new JPanel(new BorderLayout());
-    JPanel valPanel = new JPanel();
-    labPanel.setBounds(new Rectangle(7, 7, 158, 23));
-    valPanel.setBounds(new Rectangle(172, 7, 270, 23));
-    labPanel.add(label, BorderLayout.WEST);
-    valPanel.add(valBox);
-    laypanel.add(labPanel);
-    laypanel.add(valPanel);
-    valPanel.setToolTipText(tooltip);
-    labPanel.setToolTipText(tooltip);
-    valBox.setToolTipText(tooltip);
-    panel.add(laypanel);
-    panel.validate();
-    return laypanel;
-  }
-
-  public static void mgAddtoLayout(JPanel cpanel, String tooltip,
-          JLabel jLabel, JComponent name)
-  {
-    mgAddtoLayout(cpanel, tooltip, jLabel, name, null);
-  }
-
-  public static void mgAddtoLayout(JPanel cpanel, String tooltip,
-          JLabel jLabel, JComponent name, String params)
+  public static void addtoLayout(Container container, String tooltip,
+          JComponent label, JComponent comp, String constraints)
   {
-    cpanel.add(jLabel);
-    if (params == null)
-    {
-      cpanel.add(name);
-    }
-    else
-    {
-      cpanel.add(name, params);
-    }
-    name.setToolTipText(tooltip);
-    jLabel.setToolTipText(tooltip);
+    container.add(label);
+    container.add(comp, constraints);
+    comp.setToolTipText(tooltip); // this doesn't seem to show?
+    label.setToolTipText(tooltip);
   }
 
   /**
@@ -356,7 +321,7 @@ public final class JvSwingUtils
 
   /**
    * Adds a titled border to the component in the default font and position (top
-   * left), optionally witht italic text
+   * left), optionally with italic text
    * 
    * @param comp
    * @param title
index 5342c90..dcd07ef 100644 (file)
@@ -26,21 +26,25 @@ import jalview.ws.params.OptionI;
 import jalview.ws.params.ParameterI;
 import jalview.ws.params.ValueConstrainI;
 import jalview.ws.params.ValueConstrainI.ValueType;
+import jalview.ws.params.simple.LogarithmicParameter;
+import jalview.ws.params.simple.StringParameter;
 
 import java.awt.BorderLayout;
+import java.awt.Color;
 import java.awt.Component;
 import java.awt.Dimension;
+import java.awt.FlowLayout;
 import java.awt.Font;
-import java.awt.GridLayout;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -71,15 +75,33 @@ import net.miginfocom.swing.MigLayout;
  */
 public class OptsAndParamsPage
 {
-  /**
+  public static final int PARAM_WIDTH = 340;
+
+  public static final int PARAM_HEIGHT = 150;
+
+  public static final int PARAM_CLOSEDHEIGHT = 80;
+
+  URL linkImageURL = getClass().getResource("/images/link.gif");
+
+  Map<String, OptionBox> optSet = new LinkedHashMap<>();
+
+  Map<String, ParamBox> paramSet = new LinkedHashMap<>();
+
+  /*
    * compact or verbose style parameters
    */
   boolean compact = false;
 
+  OptsParametersContainerI poparent;
+
+  /**
+   * A class that models a panel rendering a single option (checkbox or choice
+   * list)
+   */
   public class OptionBox extends JPanel
           implements MouseListener, ActionListener
   {
-    JCheckBox enabled = new JCheckBox();
+    JCheckBox enabled;
 
     final URL finfo;
 
@@ -91,14 +113,13 @@ public class OptsAndParamsPage
 
     OptionI option;
 
-    JLabel optlabel = new JLabel();
-
-    JComboBox val = new JComboBox();
+    JComboBox<String> val;
 
     public OptionBox(OptionI opt)
     {
       option = opt;
-      setLayout(new BorderLayout());
+      setLayout(new FlowLayout(FlowLayout.LEFT));
+      enabled = new JCheckBox();
       enabled.setSelected(opt.isRequired()); // TODO: lock required options
       enabled.setFont(new Font("Verdana", Font.PLAIN, 11));
       enabled.setText("");
@@ -126,17 +147,19 @@ public class OptsAndParamsPage
                   JvSwingUtils.wrapTooltip(true, opt.getDescription()));
         }
       }
-      add(enabled, BorderLayout.NORTH);
-      for (Object str : opt.getPossibleValues())
+      add(enabled);
+
+      // todo combo or radio buttons?
+      val = new JComboBox<>();
+      for (String str : opt.getPossibleValues())
       {
         val.addItem(str);
       }
       val.setSelectedItem(opt.getValue());
-      if (opt.getPossibleValues().size() > 1)
+      if (opt.getPossibleValues().size() > 1 || opt.isRequired())
       {
-        setLayout(new GridLayout(1, 2));
         val.addActionListener(this);
-        add(val, BorderLayout.SOUTH);
+        add(val);
       }
       // TODO: add actionListeners for popup (to open further info),
       // and to update list of parameters if an option is enabled
@@ -218,15 +241,11 @@ public class OptsAndParamsPage
     @Override
     public void mouseEntered(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
     public void mouseExited(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
@@ -268,27 +287,49 @@ public class OptsAndParamsPage
       }
     }
 
+    /**
+     * toString representation for identification in the debugger only
+     */
+    @Override
+    public String toString()
+    {
+      return option == null ? super.toString() : option.toString();
+    }
+
   }
 
+  /**
+   * A class that models a panel rendering a single parameter
+   */
   public class ParamBox extends JPanel
           implements ChangeListener, ActionListener, MouseListener
   {
-    boolean adjusting = false;
+    /*
+     * parameter values (or their logs) are multiplied by this
+     * scaling factor to ensure an integer range for the slider
+     */
+    private int sliderScaleFactor = 1;
+
+    boolean isLogarithmicParameter;
+
+    boolean isChoiceParameter;
+
+    boolean isIntegerParameter;
+
+    boolean isStringParameter;
 
-    boolean choice = false;
+    boolean adjusting;
 
-    JComboBox choicebox;
+    JComboBox<String> choicebox;
 
-    JPanel controlPanel = new JPanel();
+    JPanel controlsPanel = new JPanel();
 
-    boolean descisvisible = false;
+    boolean descriptionIsVisible = false;
 
     JScrollPane descPanel = new JScrollPane();
 
     final URL finfo;
 
-    boolean integ = false;
-
     Object lastVal;
 
     ParameterI parameter;
@@ -297,58 +338,81 @@ public class OptsAndParamsPage
 
     JPanel settingPanel = new JPanel();
 
-    JButton showDesc = new JButton();
+    JSlider slider;
 
-    JSlider slider = null;
+    JTextArea descriptionText = new JTextArea();
 
-    JTextArea string = new JTextArea();
+    ValueConstrainI validator;
 
-    ValueConstrainI validator = null;
+    JTextField valueField;
 
-    JTextField valueField = null;
+    private String descTooltip;
 
-    public ParamBox(final OptsParametersContainerI pmlayout,
+    public ParamBox(final OptsParametersContainerI paramContainer,
             ParameterI parm)
     {
-      pmdialogbox = pmlayout;
+      pmdialogbox = paramContainer;
       finfo = parm.getFurtherDetails();
       validator = parm.getValidValue();
       parameter = parm;
+
+      isLogarithmicParameter = parm instanceof LogarithmicParameter;
+
       if (validator != null)
       {
-        integ = validator.getType() == ValueType.Integer;
-      }
-      else
-      {
-        if (parameter.getPossibleValues() != null)
+        ValueType type = validator.getType();
+        isIntegerParameter = type == ValueType.Integer;
+        isStringParameter = type == ValueType.String;
+
+        /*
+         * ensure slider has an integer range corresponding to
+         * the min-max range of the parameter
+         */
+        if (validator.getMin() != null && validator.getMax() != null
+        // && !isIntegerParameter
+                && !isStringParameter)
         {
-          choice = true;
+          double min = validator.getMin().doubleValue();
+          double max = validator.getMax().doubleValue();
+          if (isLogarithmicParameter)
+          {
+            min = Math.log(min);
+            max = Math.log(max);
+          }
+          sliderScaleFactor = (int) (1000000 / (max - min));
+          // todo scaleMin, scaleMax could also be final fields
         }
       }
 
-      if (!compact)
+      List<String> possibleValues = parameter.getPossibleValues();
+      isChoiceParameter = possibleValues != null
+              && !possibleValues.isEmpty();
+
+      if (compact)
       {
-        makeExpanderParam(parm);
+        addCompactParameter(parm);
       }
       else
       {
-        makeCompactParam(parm);
-
+        addExpandableParam(parm);
       }
     }
 
-    private void makeCompactParam(ParameterI parm)
+    /**
+     * Adds a 'compact' format parameter, with any help text shown as a tooltip
+     * 
+     * @param parm
+     */
+    private void addCompactParameter(ParameterI parm)
     {
       setLayout(new MigLayout("", "[][grow]"));
-
       String ttipText = null;
 
-      controlPanel.setLayout(new BorderLayout());
+      controlsPanel.setLayout(new BorderLayout());
 
       if (parm.getDescription() != null
               && parm.getDescription().trim().length() > 0)
       {
-        // Only create description boxes if there actually is a description.
         ttipText = (JvSwingUtils.wrapTooltip(true,
                 parm.getDescription() + (finfo != null ? "<br><img src=\""
                         + linkImageURL + "\"/>"
@@ -357,91 +421,57 @@ public class OptsAndParamsPage
                         : "")));
       }
 
-      JvSwingUtils.mgAddtoLayout(this, ttipText, new JLabel(parm.getName()),
-              controlPanel, "");
+      JvSwingUtils.addtoLayout(this, ttipText, new JLabel(parm.getName()),
+              controlsPanel, "");
       updateControls(parm);
       validate();
     }
 
-    private void makeExpanderParam(ParameterI parm)
+    /**
+     * Adds an 'expanded' format parameter, with any help shown in a panel that
+     * may be shown or hidden
+     * 
+     * @param parm
+     */
+    private void addExpandableParam(ParameterI parm)
     {
       setPreferredSize(new Dimension(PARAM_WIDTH, PARAM_CLOSEDHEIGHT));
       setBorder(new TitledBorder(parm.getName()));
       setLayout(null);
-      showDesc.setFont(new Font("Verdana", Font.PLAIN, 6));
-      showDesc.setText("+");
-      string.setFont(new Font("Verdana", Font.PLAIN, 11));
-      string.setBackground(getBackground());
+      descriptionText.setFont(new Font("Verdana", Font.PLAIN, 11));
+      descriptionText.setBackground(getBackground());
 
-      string.setEditable(false);
-      descPanel.getViewport().setView(string);
+      descriptionText.setEditable(false);
+      descPanel.getViewport().setView(descriptionText);
 
       descPanel.setVisible(false);
 
       JPanel firstrow = new JPanel();
       firstrow.setLayout(null);
-      controlPanel.setLayout(new BorderLayout());
-      controlPanel.setBounds(new Rectangle(39, 10, PARAM_WIDTH - 70,
+      controlsPanel.setLayout(new BorderLayout());
+      controlsPanel.setBounds(new Rectangle(39, 10, PARAM_WIDTH - 70,
               PARAM_CLOSEDHEIGHT - 50));
-      firstrow.add(controlPanel);
+      firstrow.add(controlsPanel);
       firstrow.setBounds(new Rectangle(10, 20, PARAM_WIDTH - 30,
               PARAM_CLOSEDHEIGHT - 30));
 
-      final ParamBox me = this;
-
       if (parm.getDescription() != null
               && parm.getDescription().trim().length() > 0)
       {
-        // Only create description boxes if there actually is a description.
-        if (finfo != null)
-        {
-          showDesc.setToolTipText(JvSwingUtils.wrapTooltip(true,
-                  MessageManager.formatMessage(
-                          "label.opt_and_params_show_brief_desc_image_link",
-                          new String[]
-                          { linkImageURL.toExternalForm() })));
-          showDesc.addMouseListener(this);
-        }
-        else
-        {
-          showDesc.setToolTipText(
-                  JvSwingUtils.wrapTooltip(true, MessageManager.getString(
-                          "label.opt_and_params_show_brief_desc")));
-        }
-        showDesc.addActionListener(new ActionListener()
-        {
-
-          @Override
-          public void actionPerformed(ActionEvent e)
-          {
-            descisvisible = !descisvisible;
-            descPanel.setVisible(descisvisible);
-            descPanel.getVerticalScrollBar().setValue(0);
-            me.setPreferredSize(new Dimension(PARAM_WIDTH,
-                    (descisvisible) ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT));
-            me.validate();
-            pmdialogbox.refreshParamLayout();
-          }
-        });
-        string.setWrapStyleWord(true);
-        string.setLineWrap(true);
-        string.setColumns(32);
-        string.setText(parm.getDescription());
-        showDesc.setBounds(new Rectangle(10, 10, 16, 16));
-        firstrow.add(showDesc);
+        addExpandableHelp(firstrow, parm);
       }
       add(firstrow);
       validator = parm.getValidValue();
       parameter = parm;
       if (validator != null)
       {
-        integ = validator.getType() == ValueType.Integer;
+        isIntegerParameter = validator.getType() == ValueType.Integer;
       }
       else
       {
         if (parameter.getPossibleValues() != null)
         {
-          choice = true;
+          isChoiceParameter = true;
         }
       }
       updateControls(parm);
@@ -451,6 +481,57 @@ public class OptsAndParamsPage
       validate();
     }
 
+    /**
+     * Adds a button which can be clicked to show or hide help text
+     * 
+     * @param container
+     * @param param
+     */
+    protected void addExpandableHelp(JPanel container, ParameterI param)
+    {
+      JButton showDescBtn = new JButton("+");
+      showDescBtn.setFont(new Font("Verdana", Font.PLAIN, 8));
+      if (finfo != null)
+      {
+        descTooltip = JvSwingUtils.wrapTooltip(true,
+                MessageManager.formatMessage(
+                        "label.opt_and_params_show_brief_desc_image_link",
+                        new String[]
+                        { linkImageURL.toExternalForm() }));
+        showDescBtn.addMouseListener(this);
+      }
+      else
+      {
+        descTooltip = JvSwingUtils.wrapTooltip(true, MessageManager
+                .getString("label.opt_and_params_show_brief_desc"));
+      }
+      showDescBtn.setToolTipText(descTooltip);
+      showDescBtn.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          descriptionIsVisible = !descriptionIsVisible;
+          showDescBtn.setText(descriptionIsVisible ? "-" : "+");
+          showDescBtn.setToolTipText(
+                  descriptionIsVisible ? null : descTooltip);
+          descPanel.setVisible(descriptionIsVisible);
+          descPanel.getVerticalScrollBar().setValue(0);
+          ParamBox.this.setPreferredSize(new Dimension(PARAM_WIDTH,
+                  (descriptionIsVisible) ? PARAM_HEIGHT
+                          : PARAM_CLOSEDHEIGHT));
+          ParamBox.this.validate();
+          pmdialogbox.refreshParamLayout();
+        }
+      });
+      descriptionText.setWrapStyleWord(true);
+      descriptionText.setLineWrap(true);
+      descriptionText.setColumns(32);
+      descriptionText.setText(param.getDescription());
+      showDescBtn.setBounds(new Rectangle(10, 10, 16, 16));
+      container.add(showDescBtn);
+    }
+
     @Override
     public void actionPerformed(ActionEvent e)
     {
@@ -458,33 +539,36 @@ public class OptsAndParamsPage
       {
         return;
       }
-      if (!choice)
+      if (!isChoiceParameter)
       {
         updateSliderFromValueField();
       }
       checkIfModified();
     }
 
+    /**
+     * Checks whether the value of this parameter has been changed and notifies
+     * the parent page accordingly
+     */
     private void checkIfModified()
     {
-      Object cstate = updateSliderFromValueField();
-      boolean notmod = false;
-      if (cstate.getClass() == lastVal.getClass())
+      if (!adjusting)
       {
-        if (cstate instanceof int[])
-        {
-          notmod = (((int[]) cstate)[0] == ((int[]) lastVal)[0]);
-        }
-        else if (cstate instanceof float[])
+        try
         {
-          notmod = (((float[]) cstate)[0] == ((float[]) lastVal)[0]);
-        }
-        else if (cstate instanceof String[])
+          adjusting = true;
+          Object newValue = updateSliderFromValueField();
+          boolean modified = true;
+          if (newValue.getClass() == lastVal.getClass())
+          {
+            modified = !newValue.equals(lastVal);
+          }
+          pmdialogbox.argSetModified(this, modified);
+        } finally
         {
-          notmod = (((String[]) cstate)[0].equals(((String[]) lastVal)[0]));
+          adjusting = false;
         }
       }
-      pmdialogbox.argSetModified(this, !notmod);
     }
 
     @Override
@@ -502,15 +586,10 @@ public class OptsAndParamsPage
       return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
     }
 
-    public int getBoxHeight()
-    {
-      return (descisvisible ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT);
-    }
-
     public ParameterI getParameter()
     {
       ParameterI prm = parameter.copy();
-      if (choice)
+      if (isChoiceParameter)
       {
         prm.setValue((String) choicebox.getSelectedItem());
       }
@@ -539,15 +618,11 @@ public class OptsAndParamsPage
     @Override
     public void mouseEntered(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
     public void mouseExited(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
@@ -562,52 +637,93 @@ public class OptsAndParamsPage
     @Override
     public void mouseReleased(MouseEvent e)
     {
-      // TODO Auto-generated method stub
-
     }
 
     @Override
     public void stateChanged(ChangeEvent e)
     {
-      if (!adjusting)
+      if (adjusting)
+      {
+        return;
+      }
+      try
       {
-        valueField.setText("" + ((integ) ? ("" + slider.getValue())
-                : ("" + slider.getValue() / 1000f)));
+        adjusting = true;
+        if (!isLogarithmicParameter)
+        {
+          /*
+           * set (int or float formatted) text field value
+           */
+          valueField.setText(isIntegerParameter
+                  ? String.valueOf(slider.getValue())
+                  : formatDouble(
+                          slider.getValue() / (float) sliderScaleFactor));
+        }
+        else
+        {
+          double value = Math.pow(Math.E,
+                  slider.getValue() / (double) sliderScaleFactor);
+          valueField.setText(formatDouble(value));
+        }
         checkIfModified();
+      } finally
+      {
+        adjusting = false;
       }
+    }
 
+    /**
+     * Answers the value formatted as a string to 3 decimal places - in
+     * scientific notation if the value is less than 0.001
+     * 
+     * @param value
+     * @return
+     */
+    String formatDouble(double value)
+    {
+      String format = value < 0.001 ? "%3.1E" : "%3.3f";
+      return String.format(format, value);
     }
 
-    public void updateControls(ParameterI parm)
+    /**
+     * Formats a number as integer or float (3dp) or scientific notation (1dp)
+     * 
+     * @param n
+     * @return
+     */
+    String formatNumber(Number n)
+    {
+      return n instanceof Integer ? String.valueOf(n.intValue())
+              : formatDouble(n.doubleValue());
+    }
+
+    void updateControls(ParameterI parm)
     {
       adjusting = true;
       boolean init = (choicebox == null && valueField == null);
       if (init)
       {
-        if (choice)
+        if (isChoiceParameter)
         {
-          choicebox = new JComboBox();
+          choicebox = new JComboBox<>();
           choicebox.addActionListener(this);
-          controlPanel.add(choicebox, BorderLayout.CENTER);
+          controlsPanel.add(choicebox, BorderLayout.CENTER);
         }
         else
         {
           slider = new JSlider();
           slider.addChangeListener(this);
-          valueField = new JTextField();
+          int cols = parm instanceof StringParameter ? 20 : 0;
+          valueField = new JTextField(cols);
           valueField.addActionListener(this);
-          valueField.addKeyListener(new KeyListener()
+          valueField.addKeyListener(new KeyAdapter()
           {
-
-            @Override
-            public void keyTyped(KeyEvent e)
-            {
-            }
-
             @Override
             public void keyReleased(KeyEvent e)
             {
-              if (e.isActionKey())
+              int keyCode = e.getKeyCode();
+              if (e.isActionKey() && keyCode != KeyEvent.VK_LEFT
+                      && keyCode != KeyEvent.VK_RIGHT)
               {
                 if (valueField.getText().trim().length() > 0)
                 {
@@ -615,32 +731,24 @@ public class OptsAndParamsPage
                 }
               }
             }
-
-            @Override
-            public void keyPressed(KeyEvent e)
-            {
-            }
           });
-          valueField.setPreferredSize(new Dimension(60, 25));
-          controlPanel.add(slider, BorderLayout.WEST);
-          controlPanel.add(valueField, BorderLayout.EAST);
-
+          valueField.setPreferredSize(new Dimension(65, 25));
+          controlsPanel.add(slider, BorderLayout.WEST);
+          controlsPanel.add(valueField, BorderLayout.EAST);
         }
       }
 
       if (parm != null)
       {
-        if (choice)
+        if (isChoiceParameter)
         {
           if (init)
           {
-            List vals = parm.getPossibleValues();
-            for (Object val : vals)
+            for (String val : parm.getPossibleValues())
             {
               choicebox.addItem(val);
             }
           }
-
           if (parm.getValue() != null)
           {
             choicebox.setSelectedItem(parm.getValue());
@@ -655,121 +763,146 @@ public class OptsAndParamsPage
       adjusting = false;
     }
 
-    public Object updateSliderFromValueField()
+    /**
+     * Action depends on the type of the input parameter:
+     * <ul>
+     * <li>if a text input, returns the trimmed value</li>
+     * <li>if a choice list, returns the selected value</li>
+     * <li>if a value slider and input field, sets the value of the slider from
+     * the value in the text field, limiting it to any defined min-max
+     * range.</li>
+     * </ul>
+     * Answers the (possibly modified) input value, as a String, Integer, Float
+     * or Double.
+     * 
+     * @return
+     */
+    Object updateSliderFromValueField()
     {
-      int iVal;
-      float fVal;
-      if (validator != null)
+      if (validator == null || isStringParameter)
       {
-        if (integ)
+        if (isChoiceParameter)
         {
-          iVal = 0;
-          try
-          {
-            valueField.setText(valueField.getText().trim());
-            iVal = Integer.valueOf(valueField.getText());
-            if (validator.getMin() != null
-                    && validator.getMin().intValue() > iVal)
-            {
-              iVal = validator.getMin().intValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-            }
-            if (validator.getMax() != null
-                    && validator.getMax().intValue() < iVal)
-            {
-              iVal = validator.getMax().intValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-            }
-          } catch (Exception e)
-          {
-          }
-          ;
-          // update value field to reflect any bound checking we performed.
-          valueField.setText("" + iVal);
-          if (validator.getMin() != null && validator.getMax() != null)
-          {
-            slider.getModel().setRangeProperties(iVal, 1,
-                    validator.getMin().intValue(),
-                    validator.getMax().intValue() + 1, true);
-          }
-          else
-          {
-            slider.setVisible(false);
-          }
-          return new int[] { iVal };
+          return choicebox.getSelectedItem();
         }
-        else
+        slider.setVisible(false);
+        return valueField.getText().trim();
+      }
+
+      valueField.setText(valueField.getText().trim());
+
+      /*
+       * ensure not outside min-max range
+       * TODO: provide some visual indicator if limit reached
+       */
+      try
+      {
+        valueField.setBackground(Color.WHITE);
+        double d = Double.parseDouble(valueField.getText());
+        if (validator.getMin() != null
+                && validator.getMin().doubleValue() > d)
         {
-          fVal = 0f;
-          try
-          {
-            valueField.setText(valueField.getText().trim());
-            fVal = Float.valueOf(valueField.getText());
-            if (validator.getMin() != null
-                    && validator.getMin().floatValue() > fVal)
-            {
-              fVal = validator.getMin().floatValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-              // update value field to reflect any bound checking we performed.
-              valueField.setText("" + fVal);
-            }
-            if (validator.getMax() != null
-                    && validator.getMax().floatValue() < fVal)
-            {
-              fVal = validator.getMax().floatValue();
-              // TODO: provide visual indication that hard limit was reached for
-              // this parameter
-              // update value field to reflect any bound checking we performed.
-              valueField.setText("" + fVal);
-            }
-          } catch (Exception e)
-          {
-          }
-          ;
-          if (validator.getMin() != null && validator.getMax() != null)
-          {
-            slider.getModel().setRangeProperties((int) (fVal * 1000f), 1,
-                    (int) (validator.getMin().floatValue() * 1000f),
-                    1 + (int) (validator.getMax().floatValue() * 1000f),
-                    true);
-          }
-          else
-          {
-            slider.setVisible(false);
-          }
-          return new float[] { fVal };
+          valueField.setText(formatNumber(validator.getMin()));
         }
+        if (validator.getMax() != null
+                && validator.getMax().doubleValue() < d)
+        {
+          valueField.setText(formatNumber(validator.getMax()));
+        }
+      } catch (NumberFormatException e)
+      {
+        valueField.setBackground(Color.yellow);
+        return Float.NaN;
       }
-      else
+
+      if (isIntegerParameter)
       {
-        if (!choice)
+        int iVal = 0;
+        try
+        {
+          iVal = Integer.valueOf(valueField.getText());
+        } catch (Exception e)
+        {
+          valueField.setBackground(Color.yellow);
+          return Integer.valueOf(0);
+        }
+
+        if (validator.getMin() != null && validator.getMax() != null)
+        {
+          slider.getModel().setRangeProperties(iVal, 1,
+                  validator.getMin().intValue(),
+                  validator.getMax().intValue() + 1, true);
+        }
+        else
         {
           slider.setVisible(false);
-          return new String[] { valueField.getText().trim() };
+        }
+        return new Integer(iVal);
+      }
+
+      if (isLogarithmicParameter)
+      {
+        double dVal = 0d;
+        try
+        {
+          double eValue = Double.valueOf(valueField.getText());
+          dVal = Math.log(eValue) * sliderScaleFactor;
+        } catch (Exception e)
+        {
+          // shouldn't be possible here
+          valueField.setBackground(Color.yellow);
+          return Double.NaN;
+        }
+        if (validator.getMin() != null && validator.getMax() != null)
+        {
+          double scaleMin = Math.log(validator.getMin().doubleValue())
+                  * sliderScaleFactor;
+          double scaleMax = Math.log(validator.getMax().doubleValue())
+                  * sliderScaleFactor;
+          slider.getModel().setRangeProperties((int) (dVal), 1,
+                  (int) scaleMin, 1 + (int) scaleMax, true);
         }
         else
         {
-          return new String[] { (String) choicebox.getSelectedItem() };
+          slider.setVisible(false);
         }
+        return new Double(dVal);
       }
 
+      float fVal = 0f;
+      try
+      {
+        fVal = Float.valueOf(valueField.getText());
+      } catch (Exception e)
+      {
+        return Float.valueOf(0f); // shouldn't happen
+      }
+      if (validator.getMin() != null && validator.getMax() != null)
+      {
+        float scaleMin = validator.getMin().floatValue()
+                * sliderScaleFactor;
+        float scaleMax = validator.getMax().floatValue()
+                * sliderScaleFactor;
+        slider.getModel().setRangeProperties(
+                (int) (fVal * sliderScaleFactor), 1, (int) scaleMin,
+                1 + (int) scaleMax, true);
+      }
+      else
+      {
+        slider.setVisible(false);
+      }
+      return new Float(fVal);
     }
   }
 
-  public static final int PARAM_WIDTH = 340;
-
-  public static final int PARAM_HEIGHT = 150;
-
-  public static final int PARAM_CLOSEDHEIGHT = 80;
-
-  public OptsAndParamsPage(OptsParametersContainerI paramContainer)
-  {
-    this(paramContainer, false);
-  }
-
+  /**
+   * Constructor with the option to show 'compact' format (parameter description
+   * as tooltip) or 'expanded' format (parameter description in a textbox which
+   * may be opened or closed). Use compact for simple description text, expanded
+   * for more wordy or formatted text.
+   * 
+   * @param paramContainer
+   */
   public OptsAndParamsPage(OptsParametersContainerI paramContainer,
           boolean compact)
   {
@@ -799,12 +932,6 @@ public class OptsAndParamsPage
     mnu.show(invoker, x, y);
   }
 
-  URL linkImageURL = getClass().getResource("/images/link.gif");
-
-  Map<String, OptionBox> optSet = new java.util.LinkedHashMap<String, OptionBox>();
-
-  Map<String, ParamBox> paramSet = new java.util.LinkedHashMap<String, ParamBox>();
-
   public Map<String, OptionBox> getOptSet()
   {
     return optSet;
@@ -825,8 +952,6 @@ public class OptsAndParamsPage
     this.paramSet = paramSet;
   }
 
-  OptsParametersContainerI poparent;
-
   OptionBox addOption(OptionI opt)
   {
     OptionBox cb = optSet.get(opt.getName());
@@ -870,11 +995,9 @@ public class OptsAndParamsPage
       }
       else
       {
-        throw new Error(MessageManager.formatMessage(
-                "error.invalid_value_for_option", new String[]
-                { string, option.getName() }));
+        throw new Error(String.format("Invalid value '%s' for option '%s'",
+                string, option.getName()));
       }
-
     }
     if (option.isRequired() && !cb.enabled.isSelected())
     {
@@ -904,7 +1027,7 @@ public class OptsAndParamsPage
    */
   public List<ArgumentI> getCurrentSettings()
   {
-    List<ArgumentI> argSet = new ArrayList<ArgumentI>();
+    List<ArgumentI> argSet = new ArrayList<>();
     for (OptionBox opts : getOptSet().values())
     {
       OptionI opt = opts.getOptionIfEnabled();
@@ -924,5 +1047,4 @@ public class OptsAndParamsPage
 
     return argSet;
   }
-
 }
index 02d54a8..ffedede 100755 (executable)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import jalview.api.AlignViewportI;
 import jalview.bin.Cache;
 import jalview.renderer.OverviewRenderer;
 import jalview.util.MessageManager;
@@ -62,7 +63,7 @@ public class OverviewPanel extends JPanel
 
   private OverviewCanvas oviewCanvas;
 
-  private AlignViewport av;
+  private AlignViewportI av;
 
   private AlignmentPanel ap;
 
index d081794..e736a11 100755 (executable)
 package jalview.gui;
 
 import jalview.analysis.AlignSeq;
+import jalview.api.AlignViewportI;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.jbgui.GPairwiseAlignPanel;
 import jalview.util.MessageManager;
-import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.event.ActionEvent;
 import java.util.Vector;
@@ -43,7 +43,7 @@ public class PairwiseAlignPanel extends GPairwiseAlignPanel
 
   private static final String DASHES = "---------------------\n";
 
-  AlignmentViewport av;
+  AlignViewportI av;
 
   Vector<SequenceI> sequences;
 
@@ -51,14 +51,13 @@ public class PairwiseAlignPanel extends GPairwiseAlignPanel
    * Creates a new PairwiseAlignPanel object.
    * 
    * @param viewport
-   *          DOCUMENT ME!
    */
-  public PairwiseAlignPanel(AlignmentViewport viewport)
+  public PairwiseAlignPanel(AlignViewportI viewport)
   {
     super();
     this.av = viewport;
 
-    sequences = new Vector<SequenceI>();
+    sequences = new Vector<>();
 
     SequenceGroup selectionGroup = viewport.getSelectionGroup();
     boolean isSelection = selectionGroup != null
index ed3d29a..a3a2422 100644 (file)
@@ -158,6 +158,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
 
   JMenuItem sequenceFeature = new JMenuItem();
 
+
   JMenuItem textColour = new JMenuItem();
 
   JMenu jMenu1 = new JMenu();
@@ -233,8 +234,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
      * currently selected sequence (if there is one):
      */
     final List<SequenceI> selectedSequence = (seq == null
-            ? Collections.<SequenceI> emptyList()
-            : Arrays.asList(seq));
+            ? Collections.<SequenceI> emptyList() : Arrays.asList(seq));
+
     buildAnnotationTypesMenus(seqShowAnnotationsMenu,
             seqHideAnnotationsMenu, selectedSequence);
     configureReferenceAnnotationsMenu(seqAddReferenceAnnotations,
@@ -461,7 +462,8 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         buildGroupURLMenu(sg, groupLinks);
       }
       // Add a 'show all structures' for the current selection
-      Hashtable<String, PDBEntry> pdbe = new Hashtable<>(), reppdb = new Hashtable<>();
+      Hashtable<String, PDBEntry> pdbe = new Hashtable<>();
+      Hashtable<String, PDBEntry> reppdb = new Hashtable<>();
 
       SequenceI sqass = null;
       for (SequenceI sq : alignPanel.av.getSequenceSelection())
index 5aab26d..5382f8d 100755 (executable)
@@ -24,6 +24,7 @@ import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
 import jalview.bin.Cache;
 import jalview.gui.Help.HelpId;
 import jalview.gui.StructureViewer.ViewerType;
+import jalview.hmmer.HmmerCommand;
 import jalview.io.FileFormatI;
 import jalview.io.JalviewFileChooser;
 import jalview.io.JalviewFileView;
@@ -36,6 +37,7 @@ import jalview.urls.UrlLinkTableModel;
 import jalview.urls.api.UrlProviderFactoryI;
 import jalview.urls.api.UrlProviderI;
 import jalview.urls.desktop.DesktopUrlProviderFactory;
+import jalview.util.FileUtils;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.util.UrlConstants;
@@ -48,6 +50,8 @@ import java.awt.Dimension;
 import java.awt.Font;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
 import java.awt.event.MouseEvent;
 import java.io.File;
 import java.util.ArrayList;
@@ -58,6 +62,7 @@ import javax.swing.JColorChooser;
 import javax.swing.JFileChooser;
 import javax.swing.JInternalFrame;
 import javax.swing.JPanel;
+import javax.swing.JTextField;
 import javax.swing.ListSelectionModel;
 import javax.swing.RowFilter;
 import javax.swing.RowSorter;
@@ -81,6 +86,12 @@ import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
  */
 public class Preferences extends GPreferences
 {
+  public static final String HMMSEARCH_SEQCOUNT = "HMMSEARCH_SEQCOUNT";
+
+  public static final String HMMINFO_GLOBAL_BACKGROUND = "HMMINFO_GLOBAL_BACKGROUND";
+
+  public static final String HMMALIGN_TRIM_TERMINI = "HMMALIGN_TRIM_TERMINI";
+
   public static final String ENABLE_SPLIT_FRAME = "ENABLE_SPLIT_FRAME";
 
   public static final String SCALE_PROTEIN_TO_CDNA = "SCALE_PROTEIN_TO_CDNA";
@@ -102,6 +113,14 @@ public class Preferences extends GPreferences
   public static final String STRUCTURE_DISPLAY = "STRUCTURE_DISPLAY";
 
   public static final String CHIMERA_PATH = "CHIMERA_PATH";
+  
+  public static final String HMMER_PATH = "HMMER_PATH";
+
+  public static final String CYGWIN_PATH = "CYGWIN_PATH";
+
+  public static final String HMMSEARCH_DB_PATHS = "HMMSEARCH_DB_PATHS";
+
+  public static final String HMMSEARCH_DBS = "HMMSEARCH_DBS";
 
   public static final String SORT_ANNOTATIONS = "SORT_ANNOTATIONS";
 
@@ -207,6 +226,63 @@ public class Preferences extends GPreferences
     frame.setMinimumSize(new Dimension(width, height));
 
     /*
+     * Set HMMER tab defaults
+     */
+    hmmrTrimTermini.setSelected(Cache.getDefault(HMMALIGN_TRIM_TERMINI, false));
+    if (Cache.getDefault(HMMINFO_GLOBAL_BACKGROUND, false))
+    {
+      hmmerBackgroundUniprot.setSelected(true);
+    }
+    else
+    {
+      hmmerBackgroundAlignment.setSelected(true);
+    }
+    hmmerSequenceCount
+            .setText(Cache.getProperty(HMMSEARCH_SEQCOUNT));
+    hmmerPath.setText(Cache.getProperty(HMMER_PATH));
+    hmmerPath.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        validateHmmerPath();
+      }
+    });
+    hmmerPath.addFocusListener(new FocusAdapter()
+    {
+      @Override
+      public void focusLost(FocusEvent e)
+      {
+        validateHmmerPath();
+      }
+    });
+    if (cygwinPath != null)
+    {
+      String path = Cache.getProperty(CYGWIN_PATH);
+      if (path == null)
+      {
+        path = FileUtils.getPathTo("bash");
+      }
+      cygwinPath.setText(path);
+      cygwinPath.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          validateCygwinPath();
+        }
+      });
+      cygwinPath.addFocusListener(new FocusAdapter()
+      {
+        @Override
+        public void focusLost(FocusEvent e)
+        {
+          validateCygwinPath();
+        }
+      });
+    }
+
+    /*
      * Set Visual tab defaults
      */
     seqLimit.setSelected(Cache.getDefault("SHOW_JVSUFFIX", true));
@@ -229,6 +305,9 @@ public class Preferences extends GPreferences
             Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM", true));
     showConsensLogo
             .setSelected(Cache.getDefault("SHOW_CONSENSUS_LOGO", false));
+    showInformationHistogram.setSelected(
+            Cache.getDefault("SHOW_INFORMATION_HISTOGRAM", true));
+    showHMMLogo.setSelected(Cache.getDefault("SHOW_HMM_LOGO", false));
     showNpTooltip
             .setSelected(Cache.getDefault("SHOW_NPFEATS_TOOLTIP", true));
     showDbRefTooltip
@@ -610,6 +689,10 @@ public class Preferences extends GPreferences
             Boolean.toString(showConsensHistogram.isSelected()));
     Cache.applicationProperties.setProperty("SHOW_CONSENSUS_LOGO",
             Boolean.toString(showConsensLogo.isSelected()));
+    Cache.applicationProperties.setProperty("SHOW_INFORMATION_HISTOGRAM",
+            Boolean.toString(showConsensHistogram.isSelected()));
+    Cache.applicationProperties.setProperty("SHOW_HMM_LOGO",
+            Boolean.toString(showHMMLogo.isSelected()));
     Cache.applicationProperties.setProperty("ANTI_ALIAS",
             Boolean.toString(smoothFont.isSelected()));
     Cache.applicationProperties.setProperty(SCALE_PROTEIN_TO_CDNA,
@@ -656,6 +739,42 @@ public class Preferences extends GPreferences
             maxColour.getBackground());
 
     /*
+     * Save HMMER settings
+     */
+    Cache.applicationProperties.setProperty(HMMALIGN_TRIM_TERMINI,
+            Boolean.toString(hmmrTrimTermini.isSelected()));
+    Cache.applicationProperties.setProperty(HMMINFO_GLOBAL_BACKGROUND,
+            Boolean.toString(hmmerBackgroundUniprot.isSelected()));
+    Cache.applicationProperties.setProperty(HMMSEARCH_SEQCOUNT,
+            hmmerSequenceCount.getText());
+    Cache.setOrRemove(HMMER_PATH, hmmerPath.getText());
+    if (cygwinPath != null)
+    {
+      Cache.setOrRemove(CYGWIN_PATH, cygwinPath.getText());
+    }
+    AlignFrame[] frames = Desktop.getAlignFrames();
+    if (frames != null && frames.length > 0)
+    {
+      for (AlignFrame f : frames)
+      {
+        f.updateHMMERStatus();
+      }
+    }
+    
+    hmmrTrimTermini.setSelected(Cache.getDefault(HMMALIGN_TRIM_TERMINI, false));
+    if (Cache.getDefault(HMMINFO_GLOBAL_BACKGROUND, false))
+    {
+      hmmerBackgroundUniprot.setSelected(true);
+    }
+    else
+    {
+      hmmerBackgroundAlignment.setSelected(true);
+    }
+    hmmerSequenceCount
+            .setText(Cache.getProperty(HMMSEARCH_SEQCOUNT));
+    hmmerPath.setText(Cache.getProperty(HMMER_PATH));
+
+    /*
      * Save Overview settings
      */
     Cache.setColourProperty(GAP_COLOUR, gapColour.getBackground());
@@ -898,6 +1017,8 @@ public class Preferences extends GPreferences
             && (identity.isSelected() || showGroupConsensus.isSelected()));
     showConsensLogo.setEnabled(annotations.isSelected()
             && (identity.isSelected() || showGroupConsensus.isSelected()));
+    showInformationHistogram.setEnabled(annotations.isSelected());
+    showHMMLogo.setEnabled(annotations.isSelected());
   }
 
   @Override
@@ -1179,6 +1300,57 @@ public class Preferences extends GPreferences
     }
     return true;
   }
+  
+  /**
+   * Returns true if the given text field contains a path to a folder that
+   * contains an executable with the given name, else false (after showing a
+   * warning dialog). The executable name will be tried with .exe appended if not
+   * found.
+   * 
+   * @param textField
+   * @param executable
+   */
+  protected boolean validateExecutablePath(JTextField textField, String executable)
+  {
+    String folder = textField.getText().trim();
+
+    if (FileUtils.getExecutable(executable, folder) != null)
+    {
+      return true;
+    }
+    if (folder.length() > 0)
+    {
+      JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+              MessageManager.formatMessage("label.executable_not_found",
+                      executable),
+              MessageManager.getString("label.invalid_folder"),
+              JvOptionPane.ERROR_MESSAGE);
+    }
+    return false;
+  }
+
+  /**
+   * Checks if a file can be executed
+   * 
+   * @param path
+   *          the path to the file
+   * @return
+   */
+  public boolean canExecute(String path)
+  {
+    File file = new File(path);
+    if (!file.canExecute())
+    {
+      file = new File(path + ".exe");
+      {
+        if (!file.canExecute())
+        {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
 
   /**
    * If Chimera is selected, check it can be found on default or user-specified
@@ -1227,6 +1399,18 @@ public class Preferences extends GPreferences
     }
   }
 
+  @Override
+  protected void validateHmmerPath()
+  {
+    validateExecutablePath(hmmerPath, HmmerCommand.HMMBUILD);
+  }
+
+  @Override
+  protected void validateCygwinPath()
+  {
+    validateExecutablePath(cygwinPath, "run");
+  }
+
   public class OptionsParam
   {
     private String name;
index 8b2e7bc..ce6bcbd 100644 (file)
@@ -1867,7 +1867,7 @@ public class SeqPanel extends JPanel
 
     // always do this - annotation has own state
     // but defer colourscheme update until hidden sequences are passed in
-    boolean vischange = stretchGroup.recalcConservation(true);
+    boolean vischange = stretchGroup.recalcAnnotations(true);
     updateOverviewAndStructs |= vischange && av.isSelectionDefinedGroup()
             && afterDrag;
     if (stretchGroup.cs != null)
index 5bff407..56d1fac 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.gui;
 
+import jalview.api.AlignViewportI;
 import jalview.api.SplitContainerI;
 import jalview.datamodel.AlignmentI;
 import jalview.jbgui.GAlignFrame;
@@ -215,8 +216,8 @@ public class SplitFrame extends GSplitFrame implements SplitContainerI
     topFrame.alignPanel.adjustAnnotationHeight();
     bottomFrame.alignPanel.adjustAnnotationHeight();
 
-    final AlignViewport topViewport = topFrame.viewport;
-    final AlignViewport bottomViewport = bottomFrame.viewport;
+    final AlignViewportI topViewport = topFrame.viewport;
+    final AlignViewportI bottomViewport = bottomFrame.viewport;
     final AlignmentI topAlignment = topViewport.getAlignment();
     final AlignmentI bottomAlignment = bottomViewport.getAlignment();
     boolean topAnnotations = topViewport.isShowAnnotation();
index 10798f6..8377a16 100644 (file)
@@ -50,7 +50,6 @@ import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.WindowEvent;
 import java.awt.event.WindowListener;
-import java.net.URL;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
@@ -63,20 +62,17 @@ import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
-import javax.swing.JSplitPane;
 import javax.swing.JTextArea;
 import javax.swing.border.TitledBorder;
 import javax.swing.event.DocumentEvent;
 import javax.swing.event.DocumentListener;
 
-import net.miginfocom.swing.MigLayout;
-
 import compbio.metadata.Argument;
 import compbio.metadata.Option;
 import compbio.metadata.Parameter;
 import compbio.metadata.Preset;
 import compbio.metadata.PresetManager;
-import compbio.metadata.RunnerConfig;
+import net.miginfocom.swing.MigLayout;
 
 /**
  * job parameter editing/browsing dialog box. User can browse existing settings
@@ -96,36 +92,33 @@ import compbio.metadata.RunnerConfig;
 public class WsJobParameters extends JPanel implements ItemListener,
         ActionListener, DocumentListener, OptsParametersContainerI
 {
-  URL linkImageURL = getClass().getResource("/images/link.gif");
+  private static final int PREFERRED_WIDTH = 540;
 
-  private static final String SVC_DEF = "Defaults"; // this is the null
-                                                    // parameter set as shown to
-                                                    // user
+  private static final int DEFAULT_HEIGHT = 640;
 
-  /**
-   * manager for options and parameters.
+  // the default parameter set shown to the user
+  private static final String SVC_DEF = "Defaults";
+
+  private int maxOptWidth = 200;
+
+  // URL linkImageURL = getClass().getResource("/images/link.gif");
+
+  /*
+   * controller for options and parameters layout
    */
-  OptsAndParamsPage opanp = new OptsAndParamsPage(this);
+  OptsAndParamsPage opanp;
 
-  /**
+  /*
    * panel containing job options
    */
-  JPanel jobOptions = new JPanel();
+  JPanel optionsPanel = new JPanel();
 
-  /**
+  /*
    * panel containing job parameters
    */
-  JPanel paramList = new JPanel();
-
-  JPanel SetNamePanel = new JPanel();
+  JPanel paramsPanel = new JPanel();
 
-  JPanel setDetails = new JPanel();
-
-  JSplitPane settingsPanel = new JSplitPane();
-
-  JPanel jobPanel = new JPanel();
-
-  JScrollPane jobOptionsPane = new JScrollPane();
+  JPanel setNamePanel = new JPanel();
 
   JButton createpref = new JButton();
 
@@ -135,81 +128,80 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
   JButton updatepref = new JButton();
 
-  JButton startjob = new JButton();
-
-  JButton canceljob = new JButton();
-
-  JComboBox setName = new JComboBox();
+  JComboBox<String> setName = new JComboBox<>();
 
   JTextArea setDescr = new JTextArea();
 
   JScrollPane paramPane = new JScrollPane();
 
-  // ScrollablePanel optsAndparams = new ScrollablePanel();
-  JPanel optsAndparams = new JPanel();
-
-  RunnerConfig serviceOptions;
-
   ParamDatastoreI paramStore;
 
-  private int MAX_OPTWIDTH = 200;
+  // set true when 'Start Job' is clicked
+  boolean startJob = false;
 
-  WsJobParameters(Jws2Instance service)
-  {
-    this(service, null);
-  }
+  JDialog frame = null;
 
-  public WsJobParameters(Jws2Instance service, WsParamSetI preset)
-  {
-    this(null, service, preset, null);
-  }
+  Jws2Instance service;
 
-  /**
-   * 
-   * @param desktop
-   *          - if null, create new JFrame outside of desktop
-   * @param service
-   * @param preset
+  /*
+   * list of service presets in the gui
    */
-  public WsJobParameters(JFrame parent, Jws2Instance service,
-          WsParamSetI preset, List<Argument> jobArgset)
+  Hashtable<String, String> servicePresets = null;
+
+  /*
+   * set if dialog is being set - so handlers will avoid spurious events
+   */
+  boolean settingDialog = false;
+
+  private Hashtable<Object, Object> modifiedElements = new Hashtable<>();
+
+  String lastParmSet = null;
+
+  public WsJobParameters(ParamDatastoreI store, WsParamSetI preset,
+          List<ArgumentI> args)
   {
-    this(parent, null, service, preset, jobArgset);
+    super();
+
+    // parameters dialog in 'compact' format (help as tooltips)
+    opanp = new OptsAndParamsPage(this, true);
+    jbInit();
+    this.paramStore = store;
+    this.service = null;
+    init(preset, args);
+    validate();
   }
 
   /**
+   * Constructor given a set of parameters and presets, a service to be invoked,
+   * and a list of (Jabaws client) arguments
    * 
-   * @param parent
    * @param paramStorei
    * @param service
    * @param preset
    * @param jobArgset
    */
-  public WsJobParameters(JFrame parent, ParamDatastoreI paramStorei,
-          Jws2Instance service, WsParamSetI preset,
-          List<Argument> jobArgset)
+  public WsJobParameters(ParamDatastoreI paramStorei, Jws2Instance service,
+          WsParamSetI preset, List<Argument> jobArgset)
   {
     super();
+
+    // parameters dialog in 'expanded' format (help text boxes)
+    opanp = new OptsAndParamsPage(this, false);
+
     jbInit();
     this.paramStore = paramStorei;
-    if (paramStore == null)
+    if (paramStore == null && service != null)
     {
       paramStore = service.getParamStore();
     }
     this.service = service;
-    // argSetModified(false);
-    // populate parameter table
-    initForService(service, preset, jobArgset);
-    // display in new JFrame attached to parent.
+    initForService(preset, jobArgset);
     validate();
   }
 
-  int response = -1;
-
-  JDialog frame = null;
-
   /**
-   * shows a modal dialog containing the parameters.
+   * Shows a modal dialog containing the parameters and Start or Cancel options.
+   * Answers true if the job is started, false if cancelled.
    * 
    * @return
    */
@@ -217,10 +209,13 @@ public class WsJobParameters extends JPanel implements ItemListener,
   {
 
     frame = new JDialog(Desktop.instance, true);
+    if (service != null)
+    {
+      frame.setTitle(MessageManager.formatMessage("label.edit_params_for",
+              new String[]
+      { service.getActionText() }));
+    }
 
-    frame.setTitle(MessageManager.formatMessage("label.edit_params_for",
-            new String[]
-            { service.getActionText() }));
     Rectangle deskr = Desktop.instance.getBounds();
     Dimension pref = this.getPreferredSize();
     frame.setBounds(
@@ -243,11 +238,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     });
     frame.setVisible(true);
 
-    if (response > 0)
-    {
-      return true;
-    }
-    return false;
+    return startJob;
   }
 
   private void jbInit()
@@ -277,7 +268,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                update_actionPerformed(e);
+                update_actionPerformed();
               }
             });
     deletepref = JvSwingUtils.makeButton(
@@ -289,7 +280,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                delete_actionPerformed(e);
+                delete_actionPerformed();
               }
             });
     createpref = JvSwingUtils.makeButton(
@@ -301,7 +292,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                create_actionPerformed(e);
+                create_actionPerformed();
               }
             });
     revertpref = JvSwingUtils.makeButton(
@@ -314,10 +305,11 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                revert_actionPerformed(e);
+                revert_actionPerformed();
               }
             });
-    startjob = JvSwingUtils.makeButton(
+
+    JButton startjob = JvSwingUtils.makeButton(
             MessageManager.getString("action.start_job"),
             MessageManager.getString("label.start_job_current_settings"),
             new ActionListener()
@@ -325,10 +317,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                startjob_actionPerformed(e);
+                startjob_actionPerformed();
               }
             });
-    canceljob = JvSwingUtils.makeButton(
+    JButton canceljob = JvSwingUtils.makeButton(
             MessageManager.getString("action.cancel_job"),
             MessageManager.getString("label.cancel_job_close_dialog"),
             new ActionListener()
@@ -336,10 +328,11 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                canceljob_actionPerformed(e);
+                canceljob_actionPerformed();
               }
             });
 
+    JPanel setDetails = new JPanel();
     setDetails.setBorder(
             new TitledBorder(MessageManager.getString("label.details")));
     setDetails.setLayout(new BorderLayout());
@@ -358,7 +351,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     setName.getEditor().addActionListener(this);
     JPanel setNameInfo = new JPanel(new FlowLayout(FlowLayout.LEFT));
     GridBagLayout gbl = new GridBagLayout();
-    SetNamePanel.setLayout(gbl);
+    setNamePanel.setLayout(gbl);
 
     JLabel setNameLabel = new JLabel(
             MessageManager.getString("label.current_parameter_set_name"));
@@ -373,9 +366,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     revertpref.setVisible(false);
     createpref.setVisible(false);
     JPanel setsavebuts = new JPanel();
-    setsavebuts.setLayout(new FlowLayout(FlowLayout.LEFT)); // GridLayout(1,2));
-    ((FlowLayout) setsavebuts.getLayout()).setHgap(10);
-    ((FlowLayout) setsavebuts.getLayout()).setVgap(0);
+    setsavebuts.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 0)); // GridLayout(1,2));
     JPanel spacer = new JPanel();
     spacer.setPreferredSize(new Dimension(2, 30));
     setsavebuts.add(spacer);
@@ -386,11 +377,11 @@ public class WsJobParameters extends JPanel implements ItemListener,
     // setsavebuts.setSize(new Dimension(150, 30));
     JPanel buttonArea = new JPanel(new GridLayout(1, 1));
     buttonArea.add(setsavebuts);
-    SetNamePanel.add(setNameInfo);
+    setNamePanel.add(setNameInfo);
     GridBagConstraints gbc = new GridBagConstraints();
     gbc.gridheight = 2;
     gbl.setConstraints(setNameInfo, gbc);
-    SetNamePanel.add(buttonArea);
+    setNamePanel.add(buttonArea);
     gbc = new GridBagConstraints();
     gbc.gridx = 0;
     gbc.gridy = 2;
@@ -400,36 +391,33 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
     // paramPane.setPreferredSize(new Dimension(360, 400));
     // paramPane.setPreferredSize(null);
-    jobOptions.setBorder(
+    optionsPanel.setBorder(
             new TitledBorder(MessageManager.getString("label.options")));
-    jobOptions.setOpaque(true);
-    paramList.setBorder(
+    optionsPanel.setOpaque(true);
+    paramsPanel.setBorder(
             new TitledBorder(MessageManager.getString("label.parameters")));
-    paramList.setOpaque(true);
-    JPanel bjo = new JPanel(new BorderLayout()),
-            bjp = new JPanel(new BorderLayout());
-    bjo.add(jobOptions, BorderLayout.CENTER);
-    bjp.add(paramList, BorderLayout.CENTER);
-    bjp.setOpaque(true);
-    bjo.setOpaque(true);
+    paramsPanel.setOpaque(true);
     // optsAndparams.setScrollableWidth(ScrollableSizeHint.FIT);
     // optsAndparams.setScrollableHeight(ScrollableSizeHint.NONE);
     // optsAndparams.setLayout(new BorderLayout());
+    JPanel optsAndparams = new JPanel();
     optsAndparams.setLayout(new BorderLayout());
-    optsAndparams.add(jobOptions, BorderLayout.NORTH);
-    optsAndparams.add(paramList, BorderLayout.CENTER);
+    optsAndparams.add(optionsPanel, BorderLayout.NORTH);
+    optsAndparams.add(paramsPanel, BorderLayout.CENTER);
     JPanel jp = new JPanel(new BorderLayout());
     jp.add(optsAndparams, BorderLayout.CENTER);
     paramPane.getViewport().setView(jp);
     paramPane.setBorder(null);
     setLayout(new BorderLayout());
+
+    JPanel jobPanel = new JPanel();
     jobPanel.setPreferredSize(null);
     jobPanel.setLayout(new BorderLayout());
     jobPanel.add(setDetails, BorderLayout.NORTH);
     jobPanel.add(paramPane, BorderLayout.CENTER);
     // jobPanel.setOrientation(JSplitPane.VERTICAL_SPLIT);
 
-    add(SetNamePanel, BorderLayout.NORTH);
+    add(setNamePanel, BorderLayout.NORTH);
     add(jobPanel, BorderLayout.CENTER);
 
     JPanel dialogpanel = new JPanel();
@@ -437,20 +425,20 @@ public class WsJobParameters extends JPanel implements ItemListener,
     dialogpanel.add(canceljob);
     // JAL-1580: setMaximumSize() doesn't work, so just size for the worst case:
     // check for null is for JUnit usage
-    final int windowHeight = Desktop.instance == null ? 540
+    final int windowHeight = Desktop.instance == null ? DEFAULT_HEIGHT
             : Desktop.instance.getHeight();
-    setPreferredSize(new Dimension(540, windowHeight));
+    // setPreferredSize(new Dimension(PREFERRED_WIDTH, windowHeight));
     add(dialogpanel, BorderLayout.SOUTH);
     validate();
   }
 
-  protected void revert_actionPerformed(ActionEvent e)
+  protected void revert_actionPerformed()
   {
     reInitDialog(lastParmSet);
     updateWebServiceMenus();
   }
 
-  protected void update_actionPerformed(ActionEvent e)
+  protected void update_actionPerformed()
   {
     if (isUserPreset)
     {
@@ -468,7 +456,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     paramStore.deletePreset(lastParmSet2);
   }
 
-  protected void delete_actionPerformed(ActionEvent e)
+  protected void delete_actionPerformed()
   {
     if (isUserPreset)
     {
@@ -479,7 +467,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     updateWebServiceMenus();
   }
 
-  protected void create_actionPerformed(ActionEvent e)
+  protected void create_actionPerformed()
   {
     String curname = ((String) setName.getSelectedItem()).trim();
     if (curname.length() > 0)
@@ -498,38 +486,25 @@ public class WsJobParameters extends JPanel implements ItemListener,
     }
   }
 
-  protected void canceljob_actionPerformed(ActionEvent e)
+  protected void canceljob_actionPerformed()
   {
-    response = 0;
+    startJob = false;
     if (frame != null)
     {
       frame.setVisible(false);
     }
   }
 
-  protected void startjob_actionPerformed(ActionEvent e)
+  protected void startjob_actionPerformed()
   {
-    response = 1;
+    startJob = true;
     if (frame != null)
     {
       frame.setVisible(false);
     }
   }
 
-  Jws2Instance service;
-
-  /**
-   * list of service presets in the gui
-   */
-  Hashtable servicePresets = null;
-
-  /**
-   * set if dialog is being set - so handlers will avoid spurious events
-   */
-  boolean settingDialog = false;
-
-  void initForService(Jws2Instance service, WsParamSetI jabap,
-          List<Argument> jabajobArgset)
+  void initForService(WsParamSetI jabap, List<Argument> jabajobArgset)
   {
     WsParamSetI p = null;
     List<ArgumentI> jobArgset = null;
@@ -541,12 +516,18 @@ public class WsJobParameters extends JPanel implements ItemListener,
                  // null;
     }
 
-    Hashtable exnames = new Hashtable();
+    init(p, jobArgset);
+
+  }
+
+  void init(WsParamSetI p, List<ArgumentI> jobArgset)
+  {
+    Hashtable<String, String> exnames = new Hashtable<>();
     for (int i = 0, iSize = setName.getItemCount(); i < iSize; i++)
     {
       exnames.put(setName.getItemAt(i), setName.getItemAt(i));
     }
-    servicePresets = new Hashtable();
+    servicePresets = new Hashtable<>();
     // Add the default entry - if not present already.
     if (!exnames.contains(SVC_DEF))
     {
@@ -554,7 +535,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
       exnames.put(SVC_DEF, SVC_DEF);
       servicePresets.put(SVC_DEF, SVC_DEF);
     }
-    String curname = (p == null ? "" : p.getName());
+
+    // String curname = (p == null ? "" : p.getName());
     for (WsParamSetI pr : paramStore.getPresets())
     {
       if (!pr.isModifiable())
@@ -594,10 +576,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
       }
     }
     settingDialog = false;
-
   }
 
-  @SuppressWarnings("unchecked")
   private void updateTable(WsParamSetI p, List<ArgumentI> jobArgset)
   {
     boolean setDefaultParams = false;
@@ -634,9 +614,9 @@ public class WsJobParameters extends JPanel implements ItemListener,
             OptionI opt = (OptionI) myarg;
             OptionBox ob = opanp.addOption(opt);
             ob.resetToDefault(setDefaultParams);
-            if (MAX_OPTWIDTH < ob.getPreferredSize().width)
+            if (maxOptWidth < ob.getPreferredSize().width)
             {
-              MAX_OPTWIDTH = ob.getPreferredSize().width;
+              maxOptWidth = ob.getPreferredSize().width;
             }
             ob.validate();
             cw += ob.getPreferredSize().width + 5;
@@ -705,8 +685,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
     return modifiedElements.size() > 0;
   }
 
-  private Hashtable modifiedElements = new Hashtable();
-
   /**
    * reset gui and modification state settings
    */
@@ -771,7 +749,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     if (b && modifiedElements.size() > 0)
     {
       makeSetNameValid(!isUserPreset);
-      SetNamePanel.revalidate();
+      setNamePanel.revalidate();
     }
     updateButtonDisplay();
   }
@@ -818,7 +796,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     // sync the gui with the preset database
     for (int i = 0, iS = setName.getItemCount(); i < iS; i++)
     {
-      String snm = (String) setName.getItemAt(i);
+      String snm = setName.getItemAt(i);
       if (snm.equals(nm))
       {
         makeupdate = true;
@@ -838,96 +816,88 @@ public class WsJobParameters extends JPanel implements ItemListener,
     settingDialog = stn;
   }
 
+  /**
+   * Rebuilds the Options and Parameters panels
+   */
   @Override
   public void refreshParamLayout()
   {
-    // optsAndparams.setPreferredSize(null);
-    FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
-    int sep = fl.getVgap();
-    boolean fh = true;
-    int os = 0,
-            s = jobOptions.getBorder().getBorderInsets(jobOptions).bottom
-                    + jobOptions.getBorder().getBorderInsets(jobOptions).top
-                    + 2 * sep;
-    /**
-     * final height for viewport
-     */
-    int finalh = s;
-    int panewidth = paramPane.getViewport().getSize().width - 120
-            - jobOptions.getBorder().getBorderInsets(jobOptions).left
-            + jobOptions.getBorder().getBorderInsets(jobOptions).right;
-
-    int w = 2 * fl.getHgap()
-            + (MAX_OPTWIDTH > OptsAndParamsPage.PARAM_WIDTH ? MAX_OPTWIDTH
-                    : OptsAndParamsPage.PARAM_WIDTH);
-    int hgap = fl.getHgap(), cw = hgap;
+    final int rightMargin = 40;
+    final int availableWidth = paramPane.getViewport().getSize().width
+            - rightMargin
+            - optionsPanel.getBorder().getBorderInsets(optionsPanel).left
+            + optionsPanel.getBorder().getBorderInsets(optionsPanel).right;
 
     if (opanp.getOptSet().size() > 0)
     {
+      int hgap = 5;
+      int currentWidth = hgap;
 
-      jobOptions.setLayout(new MigLayout("", "", ""));
-      jobOptions.removeAll();
+      /*
+       * layout constraint 'nogrid' prevents vertical column alignment,
+       * allowing controls to flow without extra space inserted to align
+       */
+      optionsPanel.setLayout(new MigLayout("nogrid", "", ""));
+      optionsPanel.removeAll();
+      JPanel lastAdded = null;
 
+      /*
+       * add each control in turn; if adding would overflow the right margin,
+       * remove and re-add the previous parameter with "wrap" (after) 
+       * in order to start a new row
+       */
       for (OptionBox pbox : opanp.getOptSet().values())
       {
         pbox.validate();
-        cw += pbox.getSize().width + hgap;
-        if (cw + 120 > panewidth)
-        {
-          jobOptions.add(pbox, "wrap");
-          // System.out.println("Wrap on "+pbox.option.getName());
-          cw = hgap + pbox.getSize().width;
-          fh = true;
-        }
-        else
+        int boxWidth = pbox.getSize().width;
+        currentWidth += boxWidth + hgap;
+        boolean wrapAfterLast = currentWidth > availableWidth
+                && lastAdded != null;
+        // System.out.println(String.format(
+        // "%s width=%d, paneWidth=%d, currentWidth=%d, wrapAfterLast=%s",
+        // pbox.toString(), boxWidth, panewidth, currentWidth,
+        // wrapAfterLast));
+        if (wrapAfterLast)
         {
-          jobOptions.add(pbox);
-        }
-        if (fh)
-        {
-          finalh += pbox.getSize().height + fl.getVgap();
-          fh = false;
+          optionsPanel.remove(lastAdded);
+          optionsPanel.add(lastAdded, "wrap");
+          currentWidth = hgap + boxWidth;
         }
+        optionsPanel.add(pbox);
+        lastAdded = pbox;
       }
-      jobOptions.revalidate();
+      optionsPanel.revalidate();
     }
     else
     {
-      jobOptions.setVisible(false);
+      optionsPanel.setVisible(false);
     }
 
-    // Now layout the parameters assuming they occupy one column - to calculate
-    // total height of options+parameters
-    fl = new FlowLayout(FlowLayout.LEFT);
-    // helpful hint from
-    // http://stackoverflow.com/questions/2743177/top-alignment-for-flowlayout
-    fl.setAlignOnBaseline(true);
     if (opanp.getParamSet().size() > 0)
     {
-      paramList.removeAll();
-      paramList.setLayout(new MigLayout("", "", ""));
-      fh = true;
+      paramsPanel.removeAll();
+      paramsPanel.setLayout(new MigLayout("", "", ""));
+      int hgap = 5;
+      int currentWidth = hgap;
+
+      JPanel lastAdded = null;
       for (ParamBox pbox : opanp.getParamSet().values())
       {
         pbox.validate();
-        cw += pbox.getSize().width + hgap;
-        if (cw + 160 > panewidth)
-        {
-          paramList.add(pbox, "wrap");
-          cw = pbox.getSize().width + hgap;
-          fh = true;
-        }
-        else
+        int boxWidth = pbox.getSize().width;
+        currentWidth += boxWidth + hgap;
+        boolean wrapAfterLast = currentWidth > availableWidth
+                && lastAdded != null;
+        if (wrapAfterLast)
         {
-          paramList.add(pbox);
+          paramsPanel.remove(lastAdded);
+          paramsPanel.add(lastAdded, "wrap");
+          currentWidth = pbox.getSize().width + hgap;
         }
-        if (fh)
-        {
-          finalh += pbox.getSize().height + fl.getVgap();
-          fh = false;
-        }
-
+        paramsPanel.add(pbox);
+        lastAdded = pbox;
       }
+
       /*
        * s = 2 * sep; for (ParamBox pbox : opanp.getParamSet().values()) {
        * pbox.validate(); s += sep +
@@ -939,11 +909,11 @@ public class WsJobParameters extends JPanel implements ItemListener,
        * .getBorder().getBorderInsets(paramList).bottom+paramList
        * .getBorder().getBorderInsets(paramList).top;
        */
-      paramList.revalidate();
+      paramsPanel.revalidate();
     }
     else
     {
-      paramList.setVisible(false);
+      paramsPanel.setVisible(false);
     }
     // TODO: waste some time trying to eliminate any unnecessary .validate calls
     // here
@@ -967,7 +937,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     int p = 0;
     if (args.length > 0)
     {
-      Vector<String> services = new Vector<String>();
+      Vector<String> services = new Vector<>();
       services.addElement(args[p++]);
       Jws2Discoverer.getDiscoverer().setServiceUrls(services);
     }
@@ -1108,8 +1078,8 @@ public class WsJobParameters extends JPanel implements ItemListener,
                 e.printStackTrace();
               }
             }
-            WsJobParameters pgui = new WsJobParameters(lastserv,
-                    new JabaPreset(lastserv, pr));
+            WsJobParameters pgui = new WsJobParameters(null, lastserv,
+                    new JabaPreset(lastserv, pr), null);
             JFrame jf = new JFrame(MessageManager
                     .formatMessage("label.ws_parameters_for", new String[]
                     { lastserv.getActionText() }));
@@ -1203,8 +1173,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
     return opanp.getCurrentSettings();
   }
 
-  String lastParmSet = null;
-
   /*
    * Hashtable<String, Object[]> editedParams = new Hashtable<String,
    * Object[]>();
@@ -1244,10 +1212,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
     int n = 0;
     // remove any set names in the drop down menu that aren't either a reserved
     // setting, or a user defined or service preset.
-    Vector items = new Vector();
+    Vector<String> items = new Vector<>();
     while (n < setName.getItemCount())
     {
-      String item = (String) setName.getItemAt(n);
+      String item = setName.getItemAt(n);
       if (!item.equals(SVC_DEF) && !paramStore.presetExists(item))
       {
         setName.removeItemAt(n);
@@ -1315,7 +1283,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     initArgSetModified();
     syncSetNamesWithStore();
     setName.setSelectedItem(lastParmSet);
-    SetNamePanel.validate();
+    setNamePanel.validate();
     validate();
     settingDialog = false;
   }
@@ -1337,11 +1305,12 @@ public class WsJobParameters extends JPanel implements ItemListener,
   @Override
   public void itemStateChanged(ItemEvent e)
   {
-    if (e.getSource() == setName && e.getStateChange() == e.SELECTED)
+    if (e.getSource() == setName
+            && e.getStateChange() == ItemEvent.SELECTED)
     {
       final String setname = (String) setName.getSelectedItem();
-      System.out.println("Item state changed for " + setname
-              + " (handling ? " + !settingDialog + ")");
+      // System.out.println("Item state changed for " + setname
+      // + " (handling ? " + !settingDialog + ")");
       if (settingDialog)
       {
         // ignore event
index d91775c..ab03d69 100644 (file)
@@ -47,20 +47,21 @@ import java.util.StringTokenizer;
  */
 public class WsParamSetManager implements ParamManager
 {
-  Hashtable<String, ParamDatastoreI> paramparsers = new Hashtable<String, ParamDatastoreI>();
+  private static final String WS_PARAM_FILES = "WS_PARAM_FILES";
+  Hashtable<String, ParamDatastoreI> paramparsers = new Hashtable<>();
 
   @Override
   public WsParamSetI[] getParameterSet(String name, String serviceUrl,
           boolean modifiable, boolean unmodifiable)
   {
-    String files = Cache.getProperty("WS_PARAM_FILES");
+    String files = Cache.getProperty(WS_PARAM_FILES);
     if (files == null)
     {
       return null;
     }
     StringTokenizer st = new StringTokenizer(files, "|");
     String pfile = null;
-    ArrayList<WsParamSetI> params = new ArrayList<WsParamSetI>();
+    ArrayList<WsParamSetI> params = new ArrayList<>();
     while (st.hasMoreTokens())
     {
       pfile = st.nextToken();
@@ -98,7 +99,8 @@ public class WsParamSetManager implements ParamManager
       } catch (IOException e)
       {
         Cache.log.info("Failed to parse parameter file " + pfile
-                + " (Check that all JALVIEW_WSPARAMFILES entries are valid!)",
+                + " (Check that all " + WS_PARAM_FILES
+                + " entries are valid!)",
                 e);
       }
     }
@@ -107,7 +109,7 @@ public class WsParamSetManager implements ParamManager
 
   private WsParamSetI[] parseParamFile(String filename) throws IOException
   {
-    List<WsParamSetI> psets = new ArrayList<WsParamSetI>();
+    List<WsParamSetI> psets = new ArrayList<>();
     InputStreamReader is = new InputStreamReader(
             new java.io.FileInputStream(new File(filename)), "UTF-8");
 
@@ -202,7 +204,7 @@ public class WsParamSetManager implements ParamManager
     }
     if (outfile != null)
     {
-      String paramFiles = jalview.bin.Cache.getDefault("WS_PARAM_FILES",
+      String paramFiles = jalview.bin.Cache.getDefault(WS_PARAM_FILES,
               filename);
       if (paramFiles.indexOf(filename) == -1)
       {
@@ -212,7 +214,7 @@ public class WsParamSetManager implements ParamManager
         }
         paramFiles = paramFiles.concat(filename);
       }
-      jalview.bin.Cache.setProperty("WS_PARAM_FILES", paramFiles);
+      jalview.bin.Cache.setProperty(WS_PARAM_FILES, paramFiles);
 
       jalview.schemabinding.version2.WebServiceParameterSet paramxml = new jalview.schemabinding.version2.WebServiceParameterSet();
 
@@ -266,7 +268,7 @@ public class WsParamSetManager implements ParamManager
     {
       return;
     }
-    String paramFiles = jalview.bin.Cache.getDefault("WS_PARAM_FILES", "");
+    String paramFiles = jalview.bin.Cache.getDefault(WS_PARAM_FILES, "");
     if (paramFiles.indexOf(filename) > -1)
     {
       String nparamFiles = new String();
@@ -279,7 +281,7 @@ public class WsParamSetManager implements ParamManager
           nparamFiles = nparamFiles.concat("|").concat(fl);
         }
       }
-      jalview.bin.Cache.setProperty("WS_PARAM_FILES", nparamFiles);
+      jalview.bin.Cache.setProperty(WS_PARAM_FILES, nparamFiles);
     }
 
     try
diff --git a/src/jalview/hmmer/HMMAlign.java b/src/jalview/hmmer/HMMAlign.java
new file mode 100644 (file)
index 0000000..b5f047e
--- /dev/null
@@ -0,0 +1,337 @@
+package jalview.hmmer;
+
+import jalview.analysis.AlignmentSorter;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentOrder;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
+import jalview.gui.SplitFrame;
+import jalview.io.DataSourceType;
+import jalview.io.StockholmFile;
+import jalview.util.FileUtils;
+import jalview.util.MessageManager;
+import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
+import jalview.ws.params.ArgumentI;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.swing.JInternalFrame;
+
+public class HMMAlign extends HmmerCommand
+{
+  static final String HMMALIGN = "hmmalign";
+
+  static final String ARG_TRIM = "--trim";
+
+  private final AlignmentI dataset;
+
+  /**
+   * Constructor for the HMMAlignThread
+   * 
+   * @param af
+   * @param args
+   */
+  public HMMAlign(AlignFrame af, List<ArgumentI> args)
+  {
+    super(af, args);
+    if (alignment.getDataset() != null)
+    {
+      dataset = alignment.getDataset();
+    }
+    else
+    {
+      dataset = null;
+    }
+  }
+
+  /**
+   * Runs the HMMAlignThread: the data on the alignment or group is exported,
+   * then the command is executed in the command line and then the data is
+   * imported and displayed in a new frame (if true). The command is executed
+   * for each segment of the alignment. Call this method directly to execute
+   * synchronously, or via start() in a new Thread for asynchronously.
+   */
+  @Override
+  public void run()
+  {
+    HiddenMarkovModel hmm = getHmmProfile();
+
+    long msgId = System.currentTimeMillis();
+    af.setProgressBar(MessageManager.getString("status.running_hmmalign"),
+            msgId);
+
+    AlignmentView msa = af.gatherSequencesForAlignment();
+    SequenceI[][] subAlignments = msa.getVisibleContigs(alignment.getGapCharacter());
+
+    List<AlignmentOrder> allOrders = new ArrayList<>();
+
+    SequenceI[][] allResults = new SequenceI[subAlignments.length][];
+    int job = 0;
+    for (SequenceI[] seqs : subAlignments)
+    {
+      Hashtable sequencesHash = stashSequences(seqs);
+      try
+      {
+        File modelFile = FileUtils.createTempFile("hmm", ".hmm");
+        File alignmentFile = FileUtils.createTempFile("output", ".sto");
+        File resultFile = FileUtils.createTempFile("input", ".sto");
+
+        exportStockholm(seqs, alignmentFile.getAbsoluteFile(), null);
+        exportHmm(hmm, modelFile.getAbsoluteFile());
+
+        boolean ran = runCommand(modelFile, alignmentFile, resultFile);
+        if (!ran)
+        {
+          JvOptionPane.showInternalMessageDialog(af, MessageManager
+                  .formatMessage("warn.command_failed", "hmmalign"));
+          return;
+        }
+
+        SequenceI[] result = importData(resultFile, allOrders);
+        recoverSequences(sequencesHash, result);
+        allResults[job] = result;
+        modelFile.delete();
+        alignmentFile.delete();
+        resultFile.delete();
+      } catch (IOException e)
+      {
+        e.printStackTrace();
+      }
+      job++;
+    }
+
+    String title = "hmmalign to " + hmm.getConsensusSequence().getName();
+    displayResults(allResults, allOrders, msa, title);
+
+    af.setProgressBar("", msgId);
+  }
+
+  /**
+   * Executes the hmmalign command and returns true if successful, false if an
+   * error is detected
+   * 
+   * @param modelFile
+   *          the HMM to align to
+   * @param alignmentFile
+   *          the sequences to align
+   * @param resultFile
+   *          the file to hold the results of alignment
+   * @return
+   * @throws IOException
+   */
+  private boolean runCommand(File modelFile, File alignmentFile,
+          File resultFile) throws IOException
+  {
+    String command = getCommandPath(HMMALIGN);
+    if (command == null)
+    {
+      return false;
+    }
+    List<String> args = new ArrayList<>();
+    args.add(command);
+
+    if (params != null)
+    {
+      for (ArgumentI arg : params)
+      {
+        String name = arg.getName();
+        if (MessageManager.getString("label.trim_termini").equals(name))
+        {
+          args.add(ARG_TRIM);
+        }
+      }
+    }
+    args.add("-o");
+    args.add(getFilePath(resultFile));
+    args.add(getFilePath(modelFile));
+    args.add(getFilePath(alignmentFile));
+    
+    return runCommand(args);
+  }
+
+  /**
+   * Imports the data from the file holding the output of hmmalign
+   * 
+   * @param resultFile
+   * @param allOrders
+   *          a list of alignment orders to add to
+   * 
+   * @return
+   * @throws IOException
+   */
+  private SequenceI[] importData(File resultFile,
+          List<AlignmentOrder> allOrders) throws IOException
+  {
+    StockholmFile file = new StockholmFile(getFilePath(resultFile),
+            DataSourceType.FILE);
+    SequenceI[] result = file.getSeqsAsArray();
+    AlignmentOrder msaorder = new AlignmentOrder(result);
+    AlignmentSorter.recoverOrder(result);
+    allOrders.add(msaorder);
+
+    return result;
+  }
+
+  /**
+   * Displays the results of all 'jobs' in a new frame
+   * 
+   * @param allResults
+   * 
+   * @param allOrders
+   * @param msa
+   * @param title
+   */
+  private void displayResults(SequenceI[][] allResults,
+          List<AlignmentOrder> allOrders, AlignmentView msa, String title)
+  {
+    AlignmentOrder[] arrOrders = allOrders
+            .toArray(new AlignmentOrder[allOrders.size()]);
+    Object[] newview = msa.getUpdatedView(allResults, arrOrders,
+            alignment.getGapCharacter());
+    SequenceI[] seqs = (SequenceI[]) newview[0];
+    HiddenColumns hidden = (HiddenColumns) newview[1];
+    Alignment al = new Alignment(seqs);
+    al.setProperty("Alignment Program", "hmmalign");
+    if (dataset != null)
+    {
+      al.setDataset(dataset);
+    }
+
+    displayInNewFrame(al, allOrders, hidden, title);
+  }
+
+  /**
+   * Displays the results in a new frame
+   * 
+   * @param al
+   *          The alignment containing the results
+   * @param alorders
+   *          The order of the sequences in the alignment on which the jobs were
+   *          run
+   * @param hidden
+   *          Hidden columns in the previous alignment
+   * @param title
+   */
+  private void displayInNewFrame(AlignmentI al,
+          List<AlignmentOrder> alorders, HiddenColumns hidden, String title)
+  {
+    AlignFrame alignFrame = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH,
+            AlignFrame.DEFAULT_HEIGHT);
+    alignFrame.setTitle(title);
+
+    FeatureRendererSettings featureSettings = af.getFeatureRenderer()
+            .getSettings();
+    // initialise with same renderer settings as in parent alignframe.
+    alignFrame.getFeatureRenderer().transferSettings(featureSettings);
+
+    addSortByMenuItems(alignFrame, alorders);
+
+    // TODO: refactor retrieve and show as new splitFrame as Desktop method
+
+    /*
+     * If alignment was requested from one half of a SplitFrame, show in a
+     * SplitFrame with the other pane similarly aligned.
+     */
+    AlignFrame requestedBy = this.af;
+    if (requestedBy != null && requestedBy.getSplitViewContainer() != null
+            && requestedBy.getSplitViewContainer()
+                    .getComplement(requestedBy) != null)
+    {
+      AlignmentI complement = requestedBy.getSplitViewContainer()
+              .getComplement(requestedBy);
+      String complementTitle = requestedBy.getSplitViewContainer()
+              .getComplementTitle(requestedBy);
+      // becomes null if the alignment window was closed before the alignment
+      // job finished.
+      AlignmentI copyComplement = new Alignment(complement);
+      // todo should this be done by copy constructor?
+      copyComplement.setGapCharacter(complement.getGapCharacter());
+      // share the same dataset (and the mappings it holds)
+      copyComplement.setDataset(complement.getDataset());
+      copyComplement.alignAs(al);
+      if (copyComplement.getHeight() > 0)
+      {
+        alignFrame.setTitle(this.af.getTitle());
+        AlignFrame af2 = new AlignFrame(copyComplement,
+                AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+        af2.setTitle(complementTitle);
+        String linkedTitle = MessageManager
+                .getString("label.linked_view_title");
+        JInternalFrame splitFrame = new SplitFrame(
+                al.isNucleotide() ? alignFrame : af2, al.isNucleotide() ? af2 : alignFrame);
+        Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1);
+        return;
+      }
+    }
+
+    /*
+     * Not from SplitFrame, or failed to created a complementary alignment
+     */
+    Desktop.addInternalFrame(alignFrame, alignFrame.getTitle(), AlignFrame.DEFAULT_WIDTH,
+            AlignFrame.DEFAULT_HEIGHT);
+  }
+
+  /**
+   * Adds sort order options to the AlignFrame menus
+   * 
+   * @param alignFrame
+   * @param alorders
+   */
+  protected void addSortByMenuItems(AlignFrame alignFrame,
+          List<AlignmentOrder> alorders)
+  {
+    // update orders
+    if (alorders.size() == 1)
+    {
+      alignFrame.addSortByOrderMenuItem("hmmalign" + " Ordering", alorders.get(0));
+    }
+    else
+    {
+      // construct a non-redundant ordering set
+      List<String> names = new ArrayList<>();
+      for (int i = 0, l = alorders.size(); i < l; i++)
+      {
+        String orderName = " Region " + i;
+        int j = i + 1;
+
+        while (j < l)
+        {
+          if (alorders.get(i).equals(alorders.get(j)))
+          {
+            alorders.remove(j);
+            l--;
+            orderName += "," + j;
+          }
+          else
+          {
+            j++;
+          }
+        }
+
+        if (i == 0 && j == 1)
+        {
+          names.add("");
+        }
+        else
+        {
+          names.add(orderName);
+        }
+      }
+      for (int i = 0, l = alorders.size(); i < l; i++)
+      {
+        alignFrame.addSortByOrderMenuItem("hmmalign" + (names.get(i)) + " Ordering",
+                alorders.get(i));
+      }
+    }
+  }
+}
diff --git a/src/jalview/hmmer/HMMBuild.java b/src/jalview/hmmer/HMMBuild.java
new file mode 100644 (file)
index 0000000..6de7029
--- /dev/null
@@ -0,0 +1,382 @@
+package jalview.hmmer;
+
+import jalview.api.AlignViewportI;
+import jalview.bin.Cache;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.JvOptionPane;
+import jalview.io.DataSourceType;
+import jalview.io.FileParse;
+import jalview.io.HMMFile;
+import jalview.util.FileUtils;
+import jalview.util.MessageManager;
+import jalview.ws.params.ArgumentI;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+/**
+ * A class that runs the hmmbuild command as a separate process.
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class HMMBuild extends HmmerCommand
+{
+  static final String ARG_AMINO = "--amino";
+
+  static final String ARG_DNA = "--dna";
+
+  static final String ARG_RNA = "--rna";
+
+  /**
+   * Constructor
+   * 
+   * @param alignFrame
+   * @param args
+   */
+  public HMMBuild(AlignFrame alignFrame, List<ArgumentI> args)
+  {
+    super(alignFrame, args);
+  }
+
+  /**
+   * Builds a HMM from an alignment (and/or groups), then imports and adds it to
+   * the alignment (and/or groups). Call this method directly to execute
+   * synchronously, or via start() in a new Thread for asynchronously.
+   */
+  @Override
+  public void run()
+  {
+    if (params == null || params.isEmpty())
+    {
+      Cache.log.error("No parameters to HMMBuild!|");
+      return;
+    }
+
+    long msgID = System.currentTimeMillis();
+    af.setProgressBar(MessageManager.getString("status.running_hmmbuild"),
+            msgID);
+
+    AlignViewportI viewport = af.getViewport();
+    try
+    {
+      /*
+       * run hmmbuild for alignment and/or groups as selected
+       */
+      List<AnnotatedCollectionI> runBuildFor = parseParameters(viewport);
+
+      for (AnnotatedCollectionI grp : runBuildFor)
+      {
+        runHMMBuild(grp);
+      }
+    } finally
+    {
+      af.setProgressBar("", msgID);
+      viewport.alignmentChanged(af.alignPanel);
+      af.buildColourMenu(); // to enable HMMER colour schemes
+    }
+  }
+
+  /**
+   * Scans the parameters to determine whether to run hmmmbuild for the whole
+   * alignment or specified subgroup(s) or both
+   * 
+   * @param viewport
+   * @return
+   */
+  protected List<AnnotatedCollectionI> parseParameters(
+          AlignViewportI viewport)
+  {
+    List<AnnotatedCollectionI> runBuildFor = new ArrayList<>();
+    boolean foundArg = false;
+
+    for (ArgumentI arg : params)
+    {
+      String name = arg.getName();
+      if (MessageManager.getString("label.hmmbuild_for").equals(name))
+      {
+        foundArg = true;
+        String value = arg.getValue();
+        if (MessageManager.getString("label.alignment").equals(value))
+        {
+          runBuildFor.add(alignment);
+        }
+        else if (MessageManager.getString("label.groups_and_alignment")
+                .equals(value))
+        {
+          runBuildFor.add(alignment);
+          runBuildFor.addAll(viewport.getAlignment().getGroups());
+        }
+        else if (MessageManager.getString("label.groups").equals(value))
+        {
+          runBuildFor.addAll(viewport.getAlignment().getGroups());
+        }
+        else if (MessageManager.getString("label.selected_group")
+                .equals(value))
+        {
+          runBuildFor.add(viewport.getSelectionGroup());
+        }
+      }
+      else if (MessageManager.getString("label.use_reference")
+              .equals(name))
+      {
+        // todo disable this option if no RF annotation on alignment
+        if (!af.getViewport().hasReferenceAnnotation())
+        {
+          JvOptionPane.showInternalMessageDialog(af, MessageManager
+                  .getString("warn.no_reference_annotation"));
+          // return;
+        }
+      }
+    }
+
+    /*
+     * default is to build for the whole alignment
+     */
+    if (!foundArg)
+    {
+      runBuildFor.add(alignment);
+    }
+
+    return runBuildFor;
+  }
+
+  /**
+   * Runs hmmbuild on the given sequences (alignment or group)
+   * 
+   * @param grp
+   */
+  private void runHMMBuild(AnnotatedCollectionI ac)
+  {
+    File hmmFile = null;
+    File alignmentFile = null;
+    try
+    {
+      hmmFile = FileUtils.createTempFile("hmm", ".hmm");
+      alignmentFile = FileUtils.createTempFile("output", ".sto");
+
+      if (ac instanceof Alignment)
+      {
+        AlignmentI al = (Alignment) ac;
+        // todo pad gaps in an unaligned SequenceGroup as well?
+        if (!al.isAligned())
+        {
+          al.padGaps();
+        }
+      }
+
+      deleteHmmSequences(ac);
+
+      List<SequenceI> copy = new ArrayList<>();
+      if (ac instanceof Alignment)
+      {
+        copy.addAll(ac.getSequences());
+      }
+      else
+      {
+        SequenceI[] sel = ((SequenceGroup) ac)
+                .getSelectionAsNewSequences((AlignmentI) ac.getContext());
+        for (SequenceI seq : sel)
+        {
+          copy.add(seq);
+        }
+      }
+
+      SequenceI[] copyArray = copy.toArray(new SequenceI[copy.size()]);
+      Hashtable sequencesHash = stashSequences(copyArray);
+
+      exportStockholm(copyArray, alignmentFile, ac);
+
+      recoverSequences(sequencesHash, copy.toArray(new SequenceI[] {}));
+
+      boolean ran = runCommand(alignmentFile, hmmFile, ac);
+      if (!ran)
+      {
+        JvOptionPane.showInternalMessageDialog(af, MessageManager
+                .formatMessage("warn.command_failed", "hmmbuild"));
+        return;
+      }
+      importData(hmmFile, ac);
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+    } finally
+    {
+      if (hmmFile != null)
+      {
+        hmmFile.delete();
+      }
+      if (alignmentFile != null)
+      {
+        alignmentFile.delete();
+      }
+    }
+  }
+
+  /**
+   * A helper method that deletes any HMM consensus sequence from the given
+   * collection, and from the parent alignment if <code>ac</code> is a subgroup
+   * 
+   * @param ac
+   */
+  void deleteHmmSequences(AnnotatedCollectionI ac)
+  {
+    List<SequenceI> hmmSeqs = ac.getHmmSequences();
+    for (SequenceI hmmSeq : hmmSeqs)
+    {
+      if (ac instanceof SequenceGroup)
+      {
+        ((SequenceGroup) ac).deleteSequence(hmmSeq, false);
+        AnnotatedCollectionI context = ac.getContext();
+        if (context != null && context instanceof AlignmentI)
+        {
+          ((AlignmentI) context).deleteSequence(hmmSeq);
+        }
+      }
+      else
+      {
+        ((AlignmentI) ac).deleteSequence(hmmSeq);
+      }
+    }
+  }
+
+  /**
+   * Constructs and executes the hmmbuild command as a separate process
+   * 
+   * @param sequencesFile
+   *          the alignment from which the HMM is built
+   * @param hmmFile
+   *          the output file to which the HMM is written
+   * @param group
+   *          alignment or group for which the hmm is generated
+   * 
+   * @return
+   * @throws IOException
+   */
+  private boolean runCommand(File sequencesFile, File hmmFile,
+          AnnotatedCollectionI group) throws IOException
+  {
+    String cmd = getCommandPath(HMMBUILD);
+    if (cmd == null)
+    {
+      return false; // executable not found
+    }
+    List<String> args = new ArrayList<>();
+    args.add(cmd);
+
+    /*
+     * HMM name (will be given to consensus sequence) is
+     * - as specified by an input parameter if set
+     * - else group name with _HMM appended (if for a group)
+     * - else align frame title with _HMM appended (if title is not too long)
+     * - else "Alignment_HMM" 
+     */
+    String name = "";
+
+    if (params != null)
+    {
+      for (ArgumentI arg : params)
+      {
+        String argName = arg.getName();
+        switch (argName)
+        {
+        case "HMM Name":
+          name = arg.getValue().trim();
+          break;
+        case "Use Reference Annotation":
+          args.add("--hand");
+          break;
+        }
+      }
+    }
+
+    if (group instanceof SequenceGroup)
+    {
+      name = ((SequenceGroup) group).getName() + "_HMM";
+    }
+
+    if ("".equals(name))
+    {
+      if (af != null && af.getTitle().length() < 15)
+      {
+        name = af.getTitle();
+      }
+      else
+      {
+        name = "Alignment_HMM";
+      }
+    }
+
+    args.add("-n");
+    args.add(name.replace(' ', '_'));
+    if (!alignment.isNucleotide())
+    {
+      args.add(ARG_AMINO); // TODO check for rna
+    }
+    else
+    {
+      args.add(ARG_DNA);
+    }
+
+    args.add(getFilePath(hmmFile));
+    args.add(getFilePath(sequencesFile));
+
+    return runCommand(args);
+  }
+
+  /**
+   * Imports the .hmm file produced by hmmbuild, and inserts the HMM consensus
+   * sequence (with attached HMM profile) as the first sequence in the alignment
+   * or group for which it was generated
+   * 
+   * @param hmmFile
+   * @param ac
+   *          (optional) the group for which the hmm was generated
+   * @throws IOException
+   */
+  private void importData(File hmmFile, AnnotatedCollectionI ac)
+          throws IOException
+  {
+    if (hmmFile.length() == 0L)
+    {
+      Cache.log.error("Error: hmmbuild produced empty hmm file");
+      return;
+    }
+
+    HMMFile file = new HMMFile(
+            new FileParse(hmmFile.getAbsolutePath(), DataSourceType.FILE));
+    SequenceI hmmSeq = file.getHMM().getConsensusSequence();
+
+    if (hmmSeq == null)
+    {
+      // hmmbuild failure not detected earlier
+      return;
+    }
+
+    if (ac instanceof SequenceGroup)
+    {
+      SequenceGroup grp = (SequenceGroup) ac;
+      char gapChar = alignment.getGapCharacter();
+      hmmSeq.insertCharAt(0, ac.getStartRes(), gapChar);
+      hmmSeq.insertCharAt(ac.getEndRes() + 1,
+              alignment.getWidth() - ac.getEndRes() - 1, gapChar);
+      SequenceI topSeq = grp.getSequencesInOrder(alignment)[0];
+      int topIndex = alignment.findIndex(topSeq);
+      alignment.insertSequenceAt(topIndex, hmmSeq);
+      ac.setSeqrep(hmmSeq);
+      grp.addSequence(hmmSeq, false);
+    }
+    else
+    {
+      alignment.insertSequenceAt(0, hmmSeq);
+    }
+  }
+}
diff --git a/src/jalview/hmmer/HMMERParamStore.java b/src/jalview/hmmer/HMMERParamStore.java
new file mode 100644 (file)
index 0000000..fbab7a9
--- /dev/null
@@ -0,0 +1,309 @@
+package jalview.hmmer;
+
+import jalview.bin.Cache;
+import jalview.datamodel.SequenceI;
+import jalview.gui.Preferences;
+import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.ParamDatastoreI;
+import jalview.ws.params.WsParamSetI;
+import jalview.ws.params.simple.BooleanOption;
+import jalview.ws.params.simple.DoubleParameter;
+import jalview.ws.params.simple.IntegerParameter;
+import jalview.ws.params.simple.LogarithmicParameter;
+import jalview.ws.params.simple.Option;
+import jalview.ws.params.simple.StringParameter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Scanner;
+
+public final class HMMERParamStore implements ParamDatastoreI
+{
+  private static final String HMMBUILD = "hmmbuild";
+
+  private static final String HMMALIGN = "hmmalign";
+
+  private static final String HMMSEARCH = "hmmsearch";
+
+  private String name;
+
+  private List<WsParamSetI> presets = new ArrayList<>();
+
+  private AlignmentViewport viewport;
+
+  private HMMERParamStore(String nam, AlignmentViewport av)
+  {
+    this.viewport = av;
+    this.name = nam;
+  }
+
+  public static HMMERParamStore forBuild(AlignmentViewport viewport)
+  {
+    return new HMMERParamStore(HMMBUILD, viewport);
+  }
+
+  public static HMMERParamStore forAlign(AlignmentViewport viewport)
+  {
+    return new HMMERParamStore(HMMALIGN, viewport);
+  }
+
+  public static HMMERParamStore forSearch(AlignmentViewport viewport)
+  {
+    return new HMMERParamStore(HMMSEARCH, viewport);
+  }
+
+  @Override
+  public List<WsParamSetI> getPresets()
+  {
+    return presets;
+  }
+
+  @Override
+  public WsParamSetI getPreset(String nam)
+  {
+    return null;
+  }
+
+  @Override
+  public List<ArgumentI> getServiceParameters()
+  {
+    List<ArgumentI> args = new ArrayList<>();
+    switch (name)
+    {
+    case HMMSEARCH:
+      getHMMSearchParams(args);
+      break;
+    case HMMALIGN:
+      getHMMAlignParams(args);
+      break;
+    case HMMBUILD:
+      getHMMBuildParams(args);
+      break;
+    default:
+    }
+
+    return args;
+  }
+
+  /**
+   * Answers default parameters for hmmsearch, taking into account any
+   * configured as user preferences
+   * 
+   * @param args
+   */
+  private void getHMMSearchParams(List<ArgumentI> args)
+  {
+    /*
+     * 'Options'
+     */
+    addChoiceOfHmm(args);
+
+    String names = Cache.getProperty(Preferences.HMMSEARCH_DBS);
+    if (names != null && !names.isEmpty())
+    {
+      List<String> databases = new ArrayList<>();
+      databases.add(MessageManager.getString(HMMSearch.THIS_ALIGNMENT_KEY));
+      Scanner nameScanner = new Scanner(names);
+
+      if (nameScanner.hasNext())
+      {
+        while (nameScanner.hasNext())
+        {
+          String next = nameScanner.next();
+          if ("null".equals(next))
+          {
+            Cache.setProperty(Preferences.HMMSEARCH_DBS, "");
+            Cache.setProperty(Preferences.HMMSEARCH_DB_PATHS, "");
+          }
+          else
+          {
+            databases.add(next);
+          }
+        }
+      }
+      nameScanner.close();
+      args.add(new StringParameter(
+              MessageManager.getString(HMMSearch.DATABASE_KEY),
+              MessageManager.getString("label.database_for_hmmsearch"),
+              true, MessageManager.getString(HMMSearch.THIS_ALIGNMENT_KEY),
+              MessageManager.getString(HMMSearch.THIS_ALIGNMENT_KEY),
+              databases));
+    }
+    args.add(new BooleanOption(
+            MessageManager.getString(HMMSearch.AUTO_ALIGN_SEQS_KEY),
+            MessageManager.getString("label.auto_align_seqs_desc"), false,
+            false, true, null));
+    args.add(new BooleanOption(
+            MessageManager.getString(HMMSearch.USE_ACCESSIONS_KEY),
+            MessageManager.getString("label.use_accessions_desc"), false,
+            false, true, null));
+    args.add(new BooleanOption(
+            MessageManager.getString(HMMSearch.TRIM_TERMINI_KEY),
+            MessageManager.getString("label.trim_termini_desc"), false,
+            false, true, null));
+
+    /*
+     * 'Parameters'
+     */
+    args.add(new IntegerParameter(
+            MessageManager.getString(HMMSearch.NUMBER_OF_RESULTS_KEY),
+            MessageManager.getString("label.number_of_results_desc"), true,
+            100, 0, 100000));
+    args.add(new StringParameter(
+            MessageManager.getString(HMMSearch.REPORTING_CUTOFF_KEY), null,
+            true, HMMSearch.CUTOFF_NONE, HMMSearch.CUTOFF_NONE,
+            Arrays.asList(HMMSearch.CUTOFF_NONE, HMMSearch.CUTOFF_EVALUE,
+                    HMMSearch.CUTOFF_SCORE)));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(HMMSearch.SEQ_EVALUE_KEY),
+            MessageManager.getString("label.seq_e_value_desc"), false, 1D,
+            1E-38, 10D));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(HMMSearch.DOM_EVALUE_KEY),
+            MessageManager.getString("label.dom_e_value_desc"), false, 1D,
+            1E-38, 10D));
+    args.add(
+            new DoubleParameter(
+                    MessageManager.getString(HMMSearch.SEQ_SCORE_KEY),
+                    MessageManager.getString("label.seq_score_desc"), false,
+                    0d, 0d, 1000d));
+    args.add(
+            new DoubleParameter(
+                    MessageManager.getString(HMMSearch.DOM_SCORE_KEY),
+                    MessageManager.getString("label.dom_score_desc"), false,
+                    0d, 0d, 1000d));
+  }
+
+  /**
+   * Answers default parameters for hmmalign, taking into account any configured
+   * as user preferences
+   * 
+   * @param args
+   */
+  private void getHMMAlignParams(List<ArgumentI> args)
+  {
+    addChoiceOfHmm(args);
+
+    boolean def = Cache.getDefault(Preferences.HMMALIGN_TRIM_TERMINI,
+            false);
+    args.add(new BooleanOption(
+            MessageManager.getString("label.trim_termini"),
+            MessageManager.getString("label.trim_termini_desc"),
+            false, false, def, null));
+  }
+
+  /**
+   * Adds an argument representing the choice of HMM sequences (profiles)
+   * against which to perform align or search, provided at least one is found
+   * 
+   * @param args
+   */
+  protected void addChoiceOfHmm(List<ArgumentI> args)
+  {
+    List<SequenceI> hmms = viewport.getAlignment().getHmmSequences();
+    if (!hmms.isEmpty())
+    {
+      List<String> options = new ArrayList<>();
+      for (SequenceI hmmSeq : hmms)
+      {
+        options.add(hmmSeq.getName());
+      }
+      String defseq = options.get(0);
+      ArgumentI arg = new StringParameter(
+              MessageManager.getString("label.use_hmm"), null, true, defseq,
+              defseq, options);
+      args.add(arg);
+    }
+  }
+
+  /**
+   * Answers default parameters for hmmbuild, taking into account any configured
+   * as user preferences
+   * 
+   * @param args
+   */
+  private void getHMMBuildParams(List<ArgumentI> args)
+  {
+    /*
+     * name to give the computed alignment HMM consensus sequence
+     * (Jalview constructs group HMM consensus sequence names)
+     */
+    String defValue = "Alignment_HMM";
+    StringParameter nameParam = new StringParameter(MessageManager.getString("label.hmm_name"),
+            MessageManager.getString("label.hmm_name_desc"), true, defValue,
+            defValue);
+    args.add(nameParam);
+
+    /*
+     * only enable Use Reference Annotation if RF is present
+     */
+    if (viewport.hasReferenceAnnotation())
+    {
+      args.add(new BooleanOption(
+              MessageManager.getString("label.use_reference"),
+              MessageManager.getString("label.use_reference_desc"), true,
+              true, true, null));
+    }
+
+    /*
+     * choice of whether to compute HMM for alignment and/or group(s)
+     * - only if there are any groups
+     */
+    if (!viewport.getAlignment().getGroups().isEmpty())
+    {
+      Collection<String> options = new ArrayList<>();
+      options.add(MessageManager.getString("label.alignment"));
+      options.add(MessageManager.getString("label.groups_and_alignment"));
+      options.add(MessageManager.getString("label.groups"));
+      options.add(MessageManager.getString("label.selected_group"));
+      args.add(new Option(MessageManager.getString("label.hmmbuild_for"),
+              MessageManager.getString("label.hmmbuild_for_desc"), true,
+              MessageManager.getString("label.alignment"),
+              MessageManager.getString("label.alignment"), options, null));
+    }
+  }
+
+  @Override
+  public boolean presetExists(String forName)
+  {
+    return false;
+  }
+
+  @Override
+  public void deletePreset(String forName)
+  {
+  }
+
+  @Override
+  public void storePreset(String presetName, String text,
+          List<ArgumentI> jobParams)
+  {
+  }
+
+  @Override
+  public void updatePreset(String oldName, String presetName, String text,
+          List<ArgumentI> jobParams)
+  {
+  }
+
+  @Override
+  public WsParamSetI parseServiceParameterFile(String forName,
+          String description, String[] serviceURL, String parameters)
+          throws IOException
+  {
+    return null;
+  }
+
+  @Override
+  public String generateServiceParameterFile(WsParamSetI pset)
+          throws IOException
+  {
+    return null;
+  }
+
+}
diff --git a/src/jalview/hmmer/HMMERPreset.java b/src/jalview/hmmer/HMMERPreset.java
new file mode 100644 (file)
index 0000000..2712259
--- /dev/null
@@ -0,0 +1,57 @@
+package jalview.hmmer;
+
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.WsParamSetI;
+
+import java.util.List;
+
+public class HMMERPreset implements WsParamSetI
+{
+
+  @Override
+  public String getName()
+  {
+    return null;
+  }
+
+  @Override
+  public String getDescription()
+  {
+    return null;
+  }
+
+  @Override
+  public String[] getApplicableUrls()
+  {
+    return null;
+  }
+
+  @Override
+  public String getSourceFile()
+  {
+    return null;
+  }
+
+  @Override
+  public void setSourceFile(String newfile)
+  {
+  }
+
+  @Override
+  public boolean isModifiable()
+  {
+    return false;
+  }
+
+  @Override
+  public List<ArgumentI> getArguments()
+  {
+    return null;
+  }
+
+  @Override
+  public void setArguments(List<ArgumentI> args)
+  {
+  }
+
+}
diff --git a/src/jalview/hmmer/HMMSearch.java b/src/jalview/hmmer/HMMSearch.java
new file mode 100644 (file)
index 0000000..efc34ae
--- /dev/null
@@ -0,0 +1,389 @@
+package jalview.hmmer;
+
+import jalview.bin.Cache;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.JvOptionPane;
+import jalview.io.DataSourceType;
+import jalview.io.FileParse;
+import jalview.io.StockholmFile;
+import jalview.util.FileUtils;
+import jalview.util.MessageManager;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.simple.BooleanOption;
+import jalview.ws.params.simple.Option;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Scanner;
+
+import javax.swing.JOptionPane;
+
+public class HMMSearch extends HmmerCommand
+{
+  static final String HMMSEARCH = "hmmsearch";
+
+  /*
+   * constants for i18n lookup of passed parameter names
+   */
+  static final String DATABASE_KEY = "label.database";
+
+  static final String THIS_ALIGNMENT_KEY = "label.this_alignment";
+
+  static final String USE_ACCESSIONS_KEY = "label.use_accessions";
+
+  static final String AUTO_ALIGN_SEQS_KEY = "label.auto_align_seqs";
+
+  static final String NUMBER_OF_RESULTS_KEY = "label.number_of_results";
+
+  static final String TRIM_TERMINI_KEY = "label.trim_termini";
+
+  static final String REPORTING_CUTOFF_KEY = "label.reporting_cutoff";
+
+  static final String CUTOFF_NONE = "None";
+
+  static final String CUTOFF_SCORE = "Score";
+
+  static final String CUTOFF_EVALUE = "E-Value";
+
+  static final String SEQ_EVALUE_KEY = "label.seq_evalue";
+
+  static final String DOM_EVALUE_KEY = "label.dom_evalue";
+
+  static final String SEQ_SCORE_KEY = "label.seq_score";
+
+  static final String DOM_SCORE_KEY = "label.dom_score";
+
+  boolean realign = false;
+
+  boolean trim = false;
+
+  int seqsToReturn = Integer.MAX_VALUE;
+
+  SequenceI[] seqs;
+
+  /**
+   * Constructor for the HMMSearchThread
+   * 
+   * @param af
+   */
+  public HMMSearch(AlignFrame af, List<ArgumentI> args)
+  {
+    super(af, args);
+  }
+
+  /**
+   * Runs the HMMSearchThread: the data on the alignment or group is exported,
+   * then the command is executed in the command line and then the data is
+   * imported and displayed in a new frame. Call this method directly to execute
+   * synchronously, or via start() in a new Thread for asynchronously.
+   */
+  @Override
+  public void run()
+  {
+    HiddenMarkovModel hmm = getHmmProfile();
+    if (hmm == null)
+    {
+      // shouldn't happen if we got this far
+      Cache.log.error("Error: no hmm for hmmsearch");
+      return;
+    }
+
+    SequenceI hmmSeq = hmm.getConsensusSequence();// af.getSelectedHMMSequence();
+    long msgId = System.currentTimeMillis();
+    af.setProgressBar(MessageManager.getString("status.running_hmmsearch"),
+            msgId);
+
+    try
+    {
+      File hmmFile = FileUtils.createTempFile("hmm", ".hmm");
+      File hitsAlignmentFile = FileUtils.createTempFile("hitAlignment",
+              ".sto");
+      File searchOutputFile = FileUtils.createTempFile("searchOutput",
+              ".sto");
+
+      exportHmm(hmm, hmmFile.getAbsoluteFile());
+
+      boolean ran = runCommand(searchOutputFile, hitsAlignmentFile, hmmFile);
+      if (!ran)
+      {
+        JvOptionPane.showInternalMessageDialog(af, MessageManager
+                .formatMessage("warn.command_failed", "hmmsearch"));
+        return;
+      }
+
+      importData(hmmSeq, hitsAlignmentFile, hmmFile, searchOutputFile);
+      // TODO make realignment of search results a step at this level
+      // and make it conditional on this.realign
+    } catch (IOException | InterruptedException e)
+    {
+      e.printStackTrace();
+    }
+    finally
+    {
+      af.setProgressBar("", msgId);
+    }
+  }
+
+  /**
+   * Executes an hmmsearch with the given hmm as input. The database to be
+   * searched is a local file as specified by the 'Database' parameter, or the
+   * current alignment (written to file) if none is specified.
+   * 
+   * @param searchOutputFile
+   * @param hitsAlignmentFile
+   * @param hmmFile
+   * 
+   * @return
+   * @throws IOException
+   */
+  private boolean runCommand(File searchOutputFile, File hitsAlignmentFile,
+          File hmmFile) throws IOException
+  {
+    String command = getCommandPath(HMMSEARCH);
+    if (command == null)
+    {
+      return false;
+    }
+
+    List<String> args = new ArrayList<>();
+    args.add(command);
+    args.add("-o");
+    args.add(getFilePath(searchOutputFile));
+    args.add("-A");
+    args.add(getFilePath(hitsAlignmentFile));
+
+    boolean dbFound = false;
+    String dbPath = "";
+    File databaseFile = null;
+
+    boolean useEvalueCutoff = false;
+    boolean useScoreCutoff = false;
+    String seqEvalueCutoff = null;
+    String domEvalueCutoff = null;
+    String seqScoreCutoff = null;
+    String domScoreCutoff = null;
+
+    if (params != null)
+    {
+      for (ArgumentI arg : params)
+      {
+        String name = arg.getName();
+        if (MessageManager.getString(NUMBER_OF_RESULTS_KEY)
+                .equals(name))
+        {
+          seqsToReturn = Integer.parseInt(arg.getValue());
+        }
+        else if (MessageManager.getString(AUTO_ALIGN_SEQS_KEY)
+                .equals(name))
+        {
+          realign = true; // TODO: not used
+        }
+        else if (MessageManager.getString(USE_ACCESSIONS_KEY)
+                .equals(name))
+        {
+          args.add("--acc");
+        }
+        else if (MessageManager.getString(REPORTING_CUTOFF_KEY)
+                .equals(name))
+        {
+          if (CUTOFF_EVALUE.equals(arg.getValue()))
+          {
+            useEvalueCutoff = true;
+          }
+          else if (CUTOFF_SCORE.equals(arg.getValue()))
+          {
+            useScoreCutoff = true;
+          }
+        }
+        else if (MessageManager.getString(SEQ_EVALUE_KEY).equals(name))
+        {
+          seqEvalueCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(SEQ_SCORE_KEY).equals(name))
+        {
+          seqScoreCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(DOM_EVALUE_KEY)
+                .equals(name))
+        {
+          domEvalueCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(DOM_SCORE_KEY).equals(name))
+        {
+          domScoreCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(TRIM_TERMINI_KEY)
+                .equals(name))
+        {
+          trim = true;
+        }
+        else if (MessageManager.getString(DATABASE_KEY).equals(name))
+        {
+          dbFound = true;
+          dbPath = arg.getValue();
+          if (!MessageManager.getString(THIS_ALIGNMENT_KEY)
+                  .equals(dbPath))
+          {
+            databaseFile = new File(dbPath);
+          }
+        }
+      }
+    }
+
+    if (useEvalueCutoff)
+    {
+      args.add("-E");
+      args.add(seqEvalueCutoff);
+      args.add("--domE");
+      args.add(domEvalueCutoff);
+    }
+    else if (useScoreCutoff)
+    {
+      args.add("-T");
+      args.add(seqScoreCutoff);
+      args.add("--domT");
+      args.add(domScoreCutoff);
+    }
+
+    if (!dbFound || MessageManager.getString(THIS_ALIGNMENT_KEY)
+            .equals(dbPath))
+    {
+      /*
+       * no external database specified for search, so
+       * export current alignment as 'database' to search,
+       * excluding any HMM consensus sequences it contains
+       */
+      databaseFile = FileUtils.createTempFile("database", ".sto");
+      AlignmentI al = af.getViewport().getAlignment();
+      AlignmentI copy = new Alignment(al);
+      List<SequenceI> hmms = copy.getHmmSequences();
+      for (SequenceI hmmSeq : hmms)
+      {
+        copy.deleteSequence(hmmSeq);
+      }
+      exportStockholm(copy.getSequencesArray(), databaseFile, null);
+    }
+
+    args.add(getFilePath(hmmFile));
+    args.add(getFilePath(databaseFile));
+
+    return runCommand(args);
+  }
+
+  /**
+   * Imports the data from the temporary file to which the output of hmmsearch
+   * is directed.
+   * 
+   * @param hmmSeq
+   */
+  private void importData(SequenceI hmmSeq, File inputAlignmentTemp,
+          File hmmTemp, File searchOutputFile)
+          throws IOException, InterruptedException
+  {
+    BufferedReader br = new BufferedReader(
+            new FileReader(inputAlignmentTemp));
+    try
+    {
+      if (br.readLine() == null)
+      {
+        JOptionPane.showMessageDialog(af,
+                MessageManager.getString("label.no_sequences_found"));
+        return;
+      }
+      StockholmFile file = new StockholmFile(new FileParse(
+              inputAlignmentTemp.getAbsolutePath(), DataSourceType.FILE));
+      seqs = file.getSeqsAsArray();
+
+      readTable(searchOutputFile);
+
+      int seqCount = Math.min(seqs.length, seqsToReturn);
+      SequenceI[] hmmAndSeqs = new SequenceI[seqCount + 1];
+      hmmAndSeqs[0] = hmmSeq;
+      System.arraycopy(seqs, 0, hmmAndSeqs, 1, seqCount);
+
+      /*
+       * and align the search results to the HMM profile
+       */
+      AlignmentI al = new Alignment(hmmAndSeqs);
+      AlignFrame frame = new AlignFrame(al, 1, 1);
+      List<ArgumentI> alignArgs = new ArrayList<>();
+      String defSeq = hmmSeq.getName();
+      List<String> options = Collections.singletonList(defSeq);
+      Option option = new Option(MessageManager.getString("label.use_hmm"),
+              "", true, defSeq, defSeq, options, null);
+      alignArgs.add(option);
+      if (trim)
+      {
+        alignArgs.add(new BooleanOption(
+                MessageManager.getString(TRIM_TERMINI_KEY),
+                MessageManager.getString("label.trim_termini_desc"), true,
+                true, true, null));
+      }
+      HmmerCommand hmmalign = new HMMAlign(frame, alignArgs);
+      hmmalign.run();
+      frame = null;
+      hmmTemp.delete();
+      inputAlignmentTemp.delete();
+      searchOutputFile.delete();
+    } finally
+    {
+      if (br != null)
+      {
+        br.close();
+      }
+    }
+  }
+
+  void readTable(File inputTableTemp) throws IOException
+  {
+    BufferedReader br = new BufferedReader(new FileReader(inputTableTemp));
+    String line = "";
+    while (!line.startsWith("Query:"))
+    {
+      line = br.readLine();
+    }
+    for (int i = 0; i < 5; i++)
+    {
+      line = br.readLine();
+    }
+
+    int index = 0;
+    while (!"  ------ inclusion threshold ------".equals(line)
+            && !"".equals(line))
+    {
+      Scanner scanner = new Scanner(line);
+
+      String str = scanner.next(); // full sequence eValue score
+      float eValue = Float.parseFloat(str);
+      int seqLength = seqs[index].getLength();
+      Annotation[] annots = new Annotation[seqLength];
+      for (int j = 0; j < seqLength; j++)
+      {
+        annots[j] = new Annotation(eValue);
+      }
+      AlignmentAnnotation annot = new AlignmentAnnotation("E-value",
+              "Score", annots);
+      annot.setScore(Double.parseDouble(str));
+      annot.setSequenceRef(seqs[index]);
+      seqs[index].addAlignmentAnnotation(annot);
+
+      scanner.close();
+      line = br.readLine();
+      index++;
+    }
+
+    br.close();
+  }
+
+}
diff --git a/src/jalview/hmmer/HmmerCommand.java b/src/jalview/hmmer/HmmerCommand.java
new file mode 100644 (file)
index 0000000..f8f2cde
--- /dev/null
@@ -0,0 +1,334 @@
+package jalview.hmmer;
+
+import jalview.analysis.SeqsetUtils;
+import jalview.bin.Cache;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.JvOptionPane;
+import jalview.gui.Preferences;
+import jalview.io.HMMFile;
+import jalview.io.StockholmFile;
+import jalview.util.FileUtils;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
+import jalview.ws.params.ArgumentI;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+/**
+ * Base class for hmmbuild, hmmalign and hmmsearch
+ * 
+ * @author TZVanaalten
+ *
+ */
+public abstract class HmmerCommand implements Runnable
+{
+  public static final String HMMBUILD = "hmmbuild";
+
+  protected final AlignFrame af;
+
+  protected final AlignmentI alignment;
+
+  protected final List<ArgumentI> params;
+
+  /**
+   * Constructor
+   * 
+   * @param alignFrame
+   * @param args
+   */
+  public HmmerCommand(AlignFrame alignFrame, List<ArgumentI> args)
+  {
+    af = alignFrame;
+    alignment = af.getViewport().getAlignment();
+    params = args;
+  }
+
+  /**
+   * Answers true if preference HMMER_PATH is set, and its value is the path to
+   * a directory that contains an executable <code>hmmbuild</code> or
+   * <code>hmmbuild.exe</code>, else false
+   * 
+   * @return
+   */
+  public static boolean isHmmerAvailable()
+  {
+    File exec = FileUtils.getExecutable(HMMBUILD,
+            Cache.getProperty(Preferences.HMMER_PATH));
+    return exec != null;
+  }
+
+  /**
+   * Uniquifies the sequences when exporting and stores their details in a
+   * hashtable
+   * 
+   * @param seqs
+   */
+  protected Hashtable stashSequences(SequenceI[] seqs)
+  {
+    return SeqsetUtils.uniquify(seqs, true);
+  }
+
+  /**
+   * Restores the sequence data lost by uniquifying
+   * 
+   * @param hashtable
+   * @param seqs
+   */
+  protected void recoverSequences(Hashtable hashtable, SequenceI[] seqs)
+  {
+    SeqsetUtils.deuniquify(hashtable, seqs);
+  }
+
+  /**
+   * Runs a command as a separate process and waits for it to complete. Answers
+   * true if the process return status is zero, else false.
+   * 
+   * @param commands
+   *          the executable command and any arguments to it
+   * @throws IOException
+   */
+  public boolean runCommand(List<String> commands)
+          throws IOException
+  {
+    List<String> args = Platform.isWindows() ? wrapWithCygwin(commands)
+            : commands;
+
+    try
+    {
+      ProcessBuilder pb = new ProcessBuilder(args);
+      pb.redirectErrorStream(true); // merge syserr to sysout
+      final Process p = pb.start();
+      new Thread(new Runnable()
+      {
+        @Override
+        public void run()
+        {
+          BufferedReader input = new BufferedReader(
+                  new InputStreamReader(p.getInputStream()));
+          try
+          {
+            String line = input.readLine();
+            while (line != null)
+            {
+              System.out.println(line);
+              line = input.readLine();
+            }
+          } catch (IOException e)
+          {
+            e.printStackTrace();
+          }
+        }
+      }).start();
+
+      p.waitFor();
+      int exitValue = p.exitValue();
+      if (exitValue != 0)
+      {
+        Cache.log.error("Command failed, return code = " + exitValue);
+        Cache.log.error("Command/args were: " + args.toString());
+      }
+      return exitValue == 0; // 0 is success, by convention
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+      return false;
+    }
+  }
+
+  /**
+   * Converts the given command to a Cygwin "bash" command wrapper. The hmmer
+   * command and any arguments to it are converted into a single parameter to the
+   * bash command.
+   * 
+   * @param commands
+   */
+  protected List<String> wrapWithCygwin(List<String> commands)
+  {
+    File bash = FileUtils.getExecutable("bash",
+            Cache.getProperty(Preferences.CYGWIN_PATH));
+    if (bash == null)
+    {
+      Cache.log.error("Cygwin shell not found");
+      return commands;
+    }
+
+    List<String> wrapped = new ArrayList<>();
+    wrapped.add(bash.getAbsolutePath());
+    wrapped.add("-c");
+
+    /*
+     * combine hmmbuild/search/align and arguments to a single string
+     */
+    StringBuilder sb = new StringBuilder();
+    for (String cmd : commands)
+    {
+      sb.append(" ").append(cmd);
+    }
+    wrapped.add(sb.toString());
+
+    return wrapped;
+  }
+
+  /**
+   * Exports an alignment, and reference (RF) annotation if present, to the
+   * specified file, in Stockholm format
+   * 
+   * @param seqs
+   * @param toFile
+   * @param annotated
+   * @throws IOException
+   */
+  public void exportStockholm(SequenceI[] seqs, File toFile,
+          AnnotatedCollectionI annotated) throws IOException
+  {
+    if (seqs == null)
+    {
+      return;
+    }
+    AlignmentI newAl = new Alignment(seqs);
+    if (!newAl.isAligned())
+    {
+      newAl.padGaps();
+    }
+
+    if (toFile != null && annotated != null)
+    {
+      AlignmentAnnotation[] annots = annotated.getAlignmentAnnotation();
+      if (annots != null)
+      {
+        for (AlignmentAnnotation annot : annots)
+        {
+          if (annot.label.contains("Reference") || "RF".equals(annot.label))
+          {
+            AlignmentAnnotation newRF;
+            if (annot.annotations.length > newAl.getWidth())
+            {
+              Annotation[] rfAnnots = new Annotation[newAl.getWidth()];
+              System.arraycopy(annot.annotations, 0, rfAnnots, 0,
+                      rfAnnots.length);
+              newRF = new AlignmentAnnotation("RF", "Reference Positions",
+                      rfAnnots);
+            }
+            else
+            {
+              newRF = new AlignmentAnnotation(annot);
+            }
+            newAl.addAnnotation(newRF);
+          }
+        }
+      }
+    }
+
+    StockholmFile file = new StockholmFile(newAl);
+    String output = file.print(seqs, false);
+    PrintWriter writer = new PrintWriter(toFile);
+    writer.println(output);
+    writer.close();
+  }
+
+  /**
+   * Answers the full path to the given hmmer executable, or null if file cannot
+   * be found or is not executable
+   * 
+   * @param cmd
+   *          command short name e.g. hmmalign
+   * @return
+   */
+  protected String getCommandPath(String cmd)
+  {
+    String binariesFolder = Cache.getProperty(Preferences.HMMER_PATH);
+    File file = FileUtils.getExecutable(cmd, binariesFolder);
+    if (file == null && af != null)
+    {
+      JvOptionPane.showInternalMessageDialog(af, MessageManager
+              .formatMessage("label.executable_not_found", cmd));
+    }
+
+    return file == null ? null : getFilePath(file);
+  }
+
+  /**
+   * Exports an HMM to the specified file
+   * 
+   * @param hmm
+   * @param hmmFile
+   * @throws IOException
+   */
+  public void exportHmm(HiddenMarkovModel hmm, File hmmFile)
+          throws IOException
+  {
+    if (hmm != null)
+    {
+      HMMFile file = new HMMFile(hmm);
+      PrintWriter writer = new PrintWriter(hmmFile);
+      writer.print(file.print());
+      writer.close();
+    }
+  }
+
+  /**
+   * Answers the HMM profile for the profile sequence the user selected (default
+   * is just the first HMM sequence in the alignment)
+   * 
+   * @return
+   */
+  protected HiddenMarkovModel getHmmProfile()
+  {
+    String alignToParamName = MessageManager.getString("label.use_hmm");
+    for (ArgumentI arg : params)
+    {
+      String name = arg.getName();
+      if (name.equals(alignToParamName))
+      {
+        String seqName = arg.getValue();
+        SequenceI hmmSeq = alignment.findName(seqName);
+        if (hmmSeq.hasHMMProfile())
+        {
+          return hmmSeq.getHMM();
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Answers an absolute path to the given file, in a format suitable for
+   * processing by a hmmer command. On a Windows platform, the native Windows file
+   * path is converted to Cygwin format, by replacing '\'with '/' and drive letter
+   * X with /cygdrive/x.
+   * 
+   * @param resultFile
+   * @return
+   */
+  protected String getFilePath(File resultFile)
+  {
+    String path = resultFile.getAbsolutePath();
+    if (Platform.isWindows())
+    {
+      // the first backslash escapes '\' for the regular expression argument
+      path = path.replaceAll("\\" + File.separator, "/");
+      int colon = path.indexOf(':');
+      if (colon > 0)
+      {
+        String drive = path.substring(0, colon);
+        path = path.replaceAll(drive + ":", "/cygdrive/" + drive);
+      }
+    }
+
+    return path;
+  }
+}
index 2340283..dcdf98e 100755 (executable)
@@ -304,9 +304,9 @@ public abstract class AlignFile extends FileParse
    */
   protected void initData()
   {
-    seqs = new Vector<SequenceI>();
-    annotations = new Vector<AlignmentAnnotation>();
-    seqGroups = new ArrayList<SequenceGroup>();
+    seqs = new Vector<>();
+    annotations = new Vector<>();
+    seqGroups = new ArrayList<>();
     parseCalled = false;
   }
 
@@ -319,7 +319,7 @@ public abstract class AlignFile extends FileParse
   @Override
   public void setSeqs(SequenceI[] s)
   {
-    seqs = new Vector<SequenceI>();
+    seqs = new Vector<>();
 
     for (int i = 0; i < s.length; i++)
     {
@@ -390,7 +390,7 @@ public abstract class AlignFile extends FileParse
   {
     if (newickStrings == null)
     {
-      newickStrings = new Vector<String[]>();
+      newickStrings = new Vector<>();
     }
     newickStrings.addElement(new String[] { treeName, newickString });
   }
@@ -414,4 +414,16 @@ public abstract class AlignFile extends FileParse
   {
     seqs.add(seq);
   }
+
+  /**
+   * Used only for hmmer statistics, so should probably be removed at some
+   * point. TODO remove this
+   * 
+   * @return
+   */
+  public Vector<AlignmentAnnotation> getAnnotations()
+  {
+    return annotations;
+  }
+
 }
index 4b33dbf..6ff5461 100644 (file)
@@ -373,8 +373,24 @@ public enum FileFormat implements FileFormatI
     {
       return false;
     }
+  },
+  HMMER3("HMMER3", "hmm", true, true)
+  {
+    @Override
+    public AlignmentFileReaderI getReader(FileParse source)
+            throws IOException
+    {
+      return new HMMFile(source);
+    }
+
+    @Override
+    public AlignmentFileWriterI getWriter(AlignmentI al)
+    {
+      return new HMMFile();
+    }
   };
 
+
   private boolean writable;
 
   private boolean readable;
index f26d6da..798875f 100755 (executable)
@@ -199,6 +199,32 @@ public class FileLoader implements Runnable
     return alignFrame;
   }
 
+  public void LoadFileOntoAlignmentWaitTillLoaded(AlignViewport viewport,
+          String file, DataSourceType sourceType, FileFormatI format)
+  {
+    this.viewport = viewport;
+    this.file = file;
+    this.protocol = sourceType;
+    this.format = format;
+    _LoadAlignmentFileWaitTillLoaded();
+  }
+
+  protected void _LoadAlignmentFileWaitTillLoaded()
+  {
+    Thread loader = new Thread(this);
+    loader.start();
+
+    while (loader.isAlive())
+    {
+      try
+      {
+        Thread.sleep(500);
+      } catch (Exception ex)
+      {
+      }
+    }
+  }
+
   public void updateRecentlyOpened()
   {
     Vector recent = new Vector();
@@ -394,6 +420,22 @@ public class FileLoader implements Runnable
             }
             // append to existing alignment
             viewport.addAlignment(al, title);
+            if (source instanceof HMMFile)
+            {
+              AlignmentI alignment = viewport.getAlignment();
+              SequenceI seq = alignment
+                      .getSequenceAt(alignment.getAbsoluteHeight() - 1);
+              if (seq.hasHMMProfile())
+              {
+                /* 
+                 * fudge: move HMM consensus sequence from last to first
+                 */
+                alignment.deleteSequence(alignment.getAbsoluteHeight() - 1);
+                alignment.insertSequenceAt(0, seq);
+              }
+              viewport.getAlignPanel().adjustAnnotationHeight();
+              viewport.updateSequenceIdColours();
+            }
           }
           else
           {
diff --git a/src/jalview/io/HMMFile.java b/src/jalview/io/HMMFile.java
new file mode 100644 (file)
index 0000000..07f29c8
--- /dev/null
@@ -0,0 +1,716 @@
+package jalview.io;
+
+import jalview.api.AlignExportSettingI;
+import jalview.api.AlignmentViewPanel;
+import jalview.datamodel.HMMNode;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceI;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+
+/**
+ * Adds capability to read in and write out HMMER3 files. .
+ * 
+ * 
+ * @author TZVanaalten
+ *
+ */
+public class HMMFile extends AlignFile
+        implements AlignmentFileReaderI, AlignmentFileWriterI
+{
+  private static final String TERMINATOR = "//";
+
+  /*
+   * keys to data in HMM file, used to store as properties of the HiddenMarkovModel
+   */
+  public static final String HMM = "HMM";
+
+  public static final String NAME = "NAME";
+
+  public static final String ACCESSION_NUMBER = "ACC";
+
+  public static final String DESCRIPTION = "DESC";
+
+  public static final String LENGTH = "LENG";
+
+  public static final String MAX_LENGTH = "MAXL";
+
+  public static final String ALPHABET = "ALPH";
+
+  public static final String DATE = "DATE";
+
+  public static final String COMMAND_LOG = "COM";
+
+  public static final String NUMBER_OF_SEQUENCES = "NSEQ";
+
+  public static final String EFF_NUMBER_OF_SEQUENCES = "EFFN";
+
+  public static final String CHECK_SUM = "CKSUM";
+
+  public static final String STATISTICS = "STATS";
+
+  public static final String COMPO = "COMPO";
+
+  public static final String GATHERING_THRESHOLD = "GA";
+
+  public static final String TRUSTED_CUTOFF = "TC";
+
+  public static final String NOISE_CUTOFF = "NC";
+
+  public static final String VITERBI = "VITERBI";
+
+  public static final String MSV = "MSV";
+
+  public static final String FORWARD = "FORWARD";
+
+  public static final String MAP = "MAP";
+
+  public static final String REFERENCE_ANNOTATION = "RF";
+
+  public static final String CONSENSUS_RESIDUE = "CONS";
+
+  public static final String CONSENSUS_STRUCTURE = "CS";
+
+  public static final String MASKED_VALUE = "MM";
+
+  private static final String ALPH_AMINO = "amino";
+
+  private static final String ALPH_DNA = "DNA";
+
+  private static final String ALPH_RNA = "RNA";
+
+  private static final String ALPHABET_AMINO = "ACDEFGHIKLMNPQRSTVWY";
+
+  private static final String ALPHABET_DNA = "ACGT";
+
+  private static final String ALPHABET_RNA = "ACGU";
+
+  private static final int NUMBER_OF_TRANSITIONS = 7;
+
+  private static final String SPACE = " ";
+
+  /*
+   * optional guide line added to an output HMMER file, purely for readability
+   */
+  private static final String TRANSITIONTYPELINE = "            m->m     m->i     m->d     i->m     i->i     d->m     d->d";
+
+  private static String NL = System.lineSeparator();
+
+  private HiddenMarkovModel hmm;
+
+  // number of symbols in the alphabet used in the hidden Markov model
+  private int numberOfSymbols;
+
+  /**
+   * Constructor that parses immediately
+   * 
+   * @param inFile
+   * @param type
+   * @throws IOException
+   */
+  public HMMFile(String inFile, DataSourceType type) throws IOException
+  {
+    super(inFile, type);
+  }
+
+  /**
+   * Constructor that parses immediately
+   * 
+   * @param source
+   * @throws IOException
+   */
+  public HMMFile(FileParse source) throws IOException
+  {
+    super(source);
+  }
+
+  /**
+   * Default constructor
+   */
+  public HMMFile()
+  {
+  }
+
+  /**
+   * Constructor for HMMFile used for exporting
+   * 
+   * @param hmm
+   */
+  public HMMFile(HiddenMarkovModel markov)
+  {
+    hmm = markov;
+  }
+
+  /**
+   * Returns the HMM produced by parsing a HMMER3 file
+   * 
+   * @return
+   */
+  public HiddenMarkovModel getHMM()
+  {
+    return hmm;
+  }
+
+  /**
+   * Gets the name of the hidden Markov model
+   * 
+   * @return
+   */
+  public String getName()
+  {
+    return hmm.getName();
+  }
+
+  /**
+   * Reads the data from HMM file into the HMM model
+   */
+  @Override
+  public void parse()
+  {
+    try
+    {
+      hmm = new HiddenMarkovModel();
+      parseHeaderLines(dataIn);
+      parseModel(dataIn);
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+    }
+  }
+
+  /**
+   * Reads the header properties from a HMMER3 file and saves them in the
+   * HiddeMarkovModel. This method exits after reading the next line after the
+   * HMM line.
+   * 
+   * @param input
+   * @throws IOException
+   */
+  void parseHeaderLines(BufferedReader input) throws IOException
+  {
+    boolean readingHeaders = true;
+    hmm.setFileHeader(input.readLine());
+    String line = input.readLine();
+    while (readingHeaders && line != null)
+    {
+      Scanner parser = new Scanner(line);
+      String next = parser.next();
+      if (ALPHABET.equals(next))
+      {
+        String alphabetType = parser.next();
+        hmm.setProperty(ALPHABET, alphabetType);
+        String alphabet = ALPH_DNA.equalsIgnoreCase(alphabetType)
+                ? ALPHABET_DNA
+                : (ALPH_RNA.equalsIgnoreCase(alphabetType) ? ALPHABET_RNA
+                        : ALPHABET_AMINO);
+        numberOfSymbols = hmm.setAlphabet(alphabet);
+      }
+      else if (HMM.equals(next))
+      {
+        readingHeaders = false;
+        String symbols = line.substring(line.indexOf(HMM) + HMM.length());
+        numberOfSymbols = hmm.setAlphabet(symbols);
+      }
+      else if (STATISTICS.equals(next))
+      {
+        parser.next();
+        String key;
+        String value;
+        key = parser.next();
+        value = parser.next() + SPACE + SPACE + parser.next();
+        hmm.setProperty(key, value);
+      }
+      else
+      {
+        String key = next;
+        String value = parser.next();
+        while (parser.hasNext())
+        {
+          value = value + SPACE + parser.next();
+        }
+        hmm.setProperty(key, value);
+      }
+      parser.close();
+      line = input.readLine();
+    }
+  }
+
+  /**
+   * Parses the model data from the HMMER3 file. The input buffer should be
+   * positioned at the (optional) COMPO line if there is one, else at the insert
+   * emissions line for the BEGIN node of the model.
+   * 
+   * @param input
+   * @throws IOException
+   */
+  void parseModel(BufferedReader input) throws IOException
+  {
+    /*
+     * specification says there must always be an HMM header (already read)
+     * and one more header (guide headings) which is skipped here
+     */
+    int nodeNo = 0;
+    String line = input.readLine();
+    List<HMMNode> nodes = new ArrayList<>();
+
+    while (line != null && !TERMINATOR.equals(line))
+    {
+      HMMNode node = new HMMNode();
+      nodes.add(node);
+      Scanner scanner = new Scanner(line);
+      String next = scanner.next();
+
+      /*
+       * expect COMPO (optional) for average match emissions
+       * or a node number followed by node's match emissions
+       */
+      if (COMPO.equals(next) || nodeNo > 0)
+      {
+        /*
+         * parse match emissions
+         */
+        double[] matches = parseDoubles(scanner, numberOfSymbols);
+        node.setMatchEmissions(matches);
+        if (!COMPO.equals(next))
+        {
+          int resNo = parseAnnotations(scanner, node);
+          if (resNo == 0)
+          {
+            /*
+             * no MAP annotation provided, just number off from 0 (begin node)
+             */
+            resNo = nodeNo;
+          }
+          node.setResidueNumber(resNo);
+        }
+        line = input.readLine();
+      }
+      scanner.close();
+
+      /*
+       * parse insert emissions
+       */
+      scanner = new Scanner(line);
+      double[] inserts = parseDoubles(scanner, numberOfSymbols);
+      node.setInsertEmissions(inserts);
+      scanner.close();
+
+      /*
+       * parse state transitions
+       */
+      line = input.readLine();
+      scanner = new Scanner(line);
+      double[] transitions = parseDoubles(scanner,
+              NUMBER_OF_TRANSITIONS);
+      node.setStateTransitions(transitions);
+      scanner.close();
+      line = input.readLine();
+
+      nodeNo++;
+    }
+
+    hmm.setNodes(nodes);
+  }
+
+  /**
+   * Parses the annotations on the match emission line and add them to the node.
+   * (See p109 of the HMMER User Guide (V3.1b2) for the specification.) Returns
+   * the residue position that the node maps to, if provided, else zero.
+   * 
+   * @param scanner
+   * @param node
+   */
+  int parseAnnotations(Scanner scanner, HMMNode node)
+  {
+    int mapTo = 0;
+
+    /*
+     * map from hmm node to sequence position, if provided
+     */
+    if (scanner.hasNext())
+    {
+      String value = scanner.next();
+      if (!"-".equals(value))
+      {
+        try
+        {
+          mapTo = Integer.parseInt(value);
+          node.setResidueNumber(mapTo);
+        } catch (NumberFormatException e)
+        {
+          // ignore
+        }
+      }
+    }
+
+    /*
+     * hmm consensus residue if provided, else '-'
+     */
+    if (scanner.hasNext())
+    {
+      node.setConsensusResidue(scanner.next().charAt(0));
+    }
+
+    /*
+     * RF reference annotation, if provided, else '-'
+     */
+    if (scanner.hasNext())
+    {
+      node.setReferenceAnnotation(scanner.next().charAt(0));
+    }
+
+    /*
+     * 'm' for masked position, if provided, else '-'
+     */
+    if (scanner.hasNext())
+    {
+      node.setMaskValue(scanner.next().charAt(0));
+    }
+
+    /*
+     * structure consensus symbol, if provided, else '-'
+     */
+    if (scanner.hasNext())
+    {
+      node.setConsensusStructure(scanner.next().charAt(0));
+    }
+
+    return mapTo;
+  }
+
+  /**
+   * Fills an array of doubles parsed from an input line
+   * 
+   * @param input
+   * @param numberOfElements
+   * @return
+   * @throws IOException
+   */
+  static double[] parseDoubles(Scanner input,
+          int numberOfElements) throws IOException
+  {
+    double[] values = new double[numberOfElements];
+    for (int i = 0; i < numberOfElements; i++)
+    {
+      if (!input.hasNext())
+      {
+        throw new IOException("Incomplete data");
+      }
+      String next = input.next();
+      if (next.contains("*"))
+      {
+        values[i] = Double.NEGATIVE_INFINITY;
+      }
+      else
+      {
+        double prob = Double.valueOf(next);
+        prob = Math.pow(Math.E, -prob);
+        values[i] = prob;
+      }
+    }
+    return values;
+  }
+
+  /**
+   * Returns a string to be added to the StringBuilder containing the entire
+   * output String.
+   * 
+   * @param initialColumnSeparation
+   *          The initial whitespace separation between the left side of the
+   *          file and first character.
+   * @param columnSeparation
+   *          The separation between subsequent data entries.
+   * @param data
+   *          The list of data to be added to the String.
+   * @return
+   */
+  String addData(int initialColumnSeparation,
+          int columnSeparation, List<String> data)
+  {
+    String line = "";
+    boolean first = true;
+    for (String value : data)
+    {
+      int sep = first ? initialColumnSeparation : columnSeparation;
+      line += String.format("%" + sep + "s", value);
+      first = false;
+    }
+    return line;
+  }
+
+  /**
+   * Converts list of characters into a list of Strings.
+   * 
+   * @param list
+   * @return Returns the list of Strings.
+   */
+  List<String> charListToStringList(List<Character> list)
+  {
+    List<String> strList = new ArrayList<>();
+    for (char value : list)
+    {
+      String strValue = Character.toString(value);
+      strList.add(strValue);
+    }
+    return strList;
+  }
+
+  /**
+   * Converts an array of doubles into a list of Strings, rounded to the nearest
+   * 5th decimal place
+   * 
+   * @param doubles
+   * @param noOfDecimals
+   * @return
+   */
+  List<String> doublesToStringList(double[] doubles)
+  {
+    List<String> strList = new ArrayList<>();
+    for (double value : doubles)
+    {
+      String strValue;
+      if (value > 0)
+      {
+        strValue = String.format("%.5f", value);
+      }
+      else if (value == -0.00000d)
+      {
+        strValue = "0.00000";
+      }
+      else
+      {
+        strValue = "*";
+      }
+      strList.add(strValue);
+    }
+    return strList;
+  }
+
+  /**
+   * Appends model data in string format to the string builder
+   * 
+   * @param output
+   */
+  void appendModelAsString(StringBuilder output)
+  {
+    output.append(HMM).append("  ");
+    String charSymbols = hmm.getSymbols();
+    for (char c : charSymbols.toCharArray())
+    {
+      output.append(String.format("%9s", c));
+    }
+    output.append(NL).append(TRANSITIONTYPELINE);
+
+    int length = hmm.getLength();
+
+    for (int nodeNo = 0; nodeNo <= length; nodeNo++)
+    {
+      String matchLine = String.format("%7s",
+              nodeNo == 0 ? COMPO : Integer.toString(nodeNo));
+
+      double[] doubleMatches = convertToLogSpace(
+              hmm.getNode(nodeNo).getMatchEmissions());
+      List<String> strMatches = doublesToStringList(doubleMatches);
+      matchLine += addData(10, 9, strMatches);
+
+      if (nodeNo != 0)
+      {
+        matchLine += SPACE + (hmm.getNodeMapPosition(nodeNo));
+        matchLine += SPACE + hmm.getConsensusResidue(nodeNo);
+        matchLine += SPACE + hmm.getReferenceAnnotation(nodeNo);
+        if (hmm.getFileHeader().contains("HMMER3/f"))
+        {
+          matchLine += SPACE + hmm.getMaskedValue(nodeNo);
+          matchLine += SPACE + hmm.getConsensusStructure(nodeNo);
+        }
+      }
+
+      output.append(NL).append(matchLine);
+      
+      String insertLine = "";
+
+      double[] doubleInserts = convertToLogSpace(
+              hmm.getNode(nodeNo).getInsertEmissions());
+      List<String> strInserts = doublesToStringList(doubleInserts);
+      insertLine += addData(17, 9, strInserts);
+
+      output.append(NL).append(insertLine);
+
+      String transitionLine = "";
+      double[] doubleTransitions = convertToLogSpace(
+              hmm.getNode(nodeNo).getStateTransitions());
+      List<String> strTransitions = doublesToStringList(
+              doubleTransitions);
+      transitionLine += addData(17, 9, strTransitions);
+
+      output.append(NL).append(transitionLine);
+    }
+  }
+
+  /**
+   * Appends formatted HMM file properties to the string builder
+   * 
+   * @param output
+   */
+  void appendProperties(StringBuilder output)
+  {
+    output.append(hmm.getFileHeader());
+
+    String format = "%n%-5s %1s";
+    appendProperty(output, format, NAME);
+    appendProperty(output, format, ACCESSION_NUMBER);
+    appendProperty(output, format, DESCRIPTION);
+    appendProperty(output, format, LENGTH);
+    appendProperty(output, format, MAX_LENGTH);
+    appendProperty(output, format, ALPHABET);
+    appendBooleanProperty(output, format, REFERENCE_ANNOTATION);
+    appendBooleanProperty(output, format, MASKED_VALUE);
+    appendBooleanProperty(output, format, CONSENSUS_RESIDUE);
+    appendBooleanProperty(output, format, CONSENSUS_STRUCTURE);
+    appendBooleanProperty(output, format, MAP);
+    appendProperty(output, format, DATE);
+    appendProperty(output, format, NUMBER_OF_SEQUENCES);
+    appendProperty(output, format, EFF_NUMBER_OF_SEQUENCES);
+    appendProperty(output, format, CHECK_SUM);
+    appendProperty(output, format, GATHERING_THRESHOLD);
+    appendProperty(output, format, TRUSTED_CUTOFF);
+    appendProperty(output, format, NOISE_CUTOFF);
+
+    if (hmm.getMSV() != null)
+    {
+      format = "%n%-19s %18s";
+      output.append(String.format(format, "STATS LOCAL MSV", hmm.getMSV()));
+
+      output.append(String.format(format, "STATS LOCAL VITERBI",
+              hmm.getViterbi()));
+
+      output.append(String.format(format, "STATS LOCAL FORWARD",
+              hmm.getForward()));
+    }
+  }
+
+  /**
+   * Appends 'yes' or 'no' for the given property, according to whether or not
+   * it is set in the HMM
+   * 
+   * @param output
+   * @param format
+   * @param propertyName
+   */
+  private void appendBooleanProperty(StringBuilder output, String format,
+          String propertyName)
+  {
+    boolean set = hmm.getBooleanProperty(propertyName);
+    output.append(String.format(format, propertyName,
+            set ? HiddenMarkovModel.YES : HiddenMarkovModel.NO));
+  }
+
+  /**
+   * Appends the value of the given property to the output, if not null
+   * 
+   * @param output
+   * @param format
+   * @param propertyName
+   */
+  private void appendProperty(StringBuilder output, String format,
+          String propertyName)
+  {
+    String value = hmm.getProperty(propertyName);
+    if (value != null)
+    {
+      output.append(String.format(format, propertyName, value));
+    }
+  }
+
+  @Override
+  public String print(SequenceI[] sequences, boolean jvsuffix)
+  {
+    if (sequences[0].getHMM() != null)
+    {
+      hmm = sequences[0].getHMM();
+    }
+    return print();
+  }
+
+  /**
+   * Prints the .hmm file to a String.
+   * 
+   * @return
+   */
+  public String print()
+  {
+    StringBuilder output = new StringBuilder();
+    appendProperties(output);
+    output.append(NL);
+    appendModelAsString(output);
+    output.append(NL).append(TERMINATOR).append(NL);
+    return output.toString();
+  }
+
+  /**
+   * Converts the probabilities contained in an array into log space
+   * 
+   * @param ds
+   */
+  double[] convertToLogSpace(double[] ds)
+  {
+    double[] converted = new double[ds.length];
+    for (int i = 0; i < ds.length; i++)
+    {
+      double prob = ds[i];
+      double logProb = -1 * Math.log(prob);
+
+      converted[i] = logProb;
+    }
+    return converted;
+  }
+
+  /**
+   * Returns the HMM sequence produced by reading a .hmm file.
+   */
+  @Override
+  public SequenceI[] getSeqsAsArray()
+  {
+    SequenceI hmmSeq = hmm.getConsensusSequence();
+    SequenceI[] seq = new SequenceI[1];
+    seq[0] = hmmSeq;
+    return seq;
+  }
+
+  @Override
+  public void setNewlineString(String newLine)
+  {
+    NL = newLine;
+  }
+
+  @Override
+  public void setExportSettings(AlignExportSettingI exportSettings)
+  {
+
+  }
+
+  @Override
+  public void configureForView(AlignmentViewPanel viewpanel)
+  {
+
+  }
+
+  @Override
+  public boolean hasWarningMessage()
+  {
+    return false;
+  }
+
+  @Override
+  public String getWarningMessage()
+  {
+    return "warning message";
+  }
+
+}
+
index ff959b0..ad5884c 100755 (executable)
@@ -150,6 +150,11 @@ public class IdentifyFile
           reply = FileFormat.ScoreMatrix;
           break;
         }
+        if (data.startsWith("HMMER3"))
+        {
+          reply = FileFormat.HMMER3;
+          break;
+        }
         if (data.startsWith("H ") && !aaIndexHeaderRead)
         {
           aaIndexHeaderRead = true;
index f5b5177..58b171d 100644 (file)
@@ -28,6 +28,7 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.DBRefSource;
 import jalview.datamodel.Mapping;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
@@ -42,10 +43,12 @@ import java.io.FileReader;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Hashtable;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Vector;
 
 import com.stevesoft.pat.Regex;
@@ -76,23 +79,48 @@ public class StockholmFile extends AlignFile
 {
   private static final String ANNOTATION = "annotation";
 
-  private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
+  private static final char UNDERSCORE = '_';
 
-  private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
+  // private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
+  // private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
 
   public static final Regex DETECT_BRACKETS = new Regex(
           "(<|>|\\[|\\]|\\(|\\)|\\{|\\})");
 
-  StringBuffer out; // output buffer
+  /*
+   * lookup table of Stockholm 'feature' (annotation) types
+   * see http://sonnhammer.sbc.su.se/Stockholm.html
+   */
+  private static Map<String, String> featureTypes = null;
+
+  static
+  {
+    featureTypes = new HashMap<>();
+    featureTypes.put("SS", "Secondary Structure");
+    featureTypes.put("SA", "Surface Accessibility");
+    featureTypes.put("TM", "transmembrane");
+    featureTypes.put("PP", "Posterior Probability");
+    featureTypes.put("LI", "ligand binding");
+    featureTypes.put("AS", "active site");
+    featureTypes.put("IN", "intron");
+    featureTypes.put("IR", "interacting residue");
+    featureTypes.put("AC", "accession");
+    featureTypes.put("OS", "organism");
+    featureTypes.put("CL", "class");
+    featureTypes.put("DE", "description");
+    featureTypes.put("DR", "reference");
+    featureTypes.put("LO", "look");
+    featureTypes.put("RF", "Reference Positions");
+  }
 
-  AlignmentI al;
+  private AlignmentI al;
 
   public StockholmFile()
   {
   }
 
   /**
-   * Creates a new StockholmFile object for output.
+   * Creates a new StockholmFile object for output
    */
   public StockholmFile(AlignmentI al)
   {
@@ -110,6 +138,47 @@ public class StockholmFile extends AlignFile
     super(source);
   }
 
+  /**
+   * Answers the readable description for a (case-sensitive) annotation type
+   * code, for example "Reference Positions" for "RF". Returns the type code if
+   * no description is found.
+   * 
+   * @param id
+   * @return
+   */
+  public static String typeToDescription(String id)
+  {
+    if (featureTypes.containsKey(id))
+    {
+      return featureTypes.get(id);
+    }
+    System.err.println(
+            "Warning : Unknown Stockholm annotation type code " + id);
+    return id;
+  }
+
+  /**
+   * Answers the annotation type code for a (non-case-sensitive) readable
+   * description, for example "RF" for "Reference Positions" (or null if not
+   * found)
+   * 
+   * @param description
+   * @return
+   */
+  public static String descriptionToType(String description)
+  {
+    for (Entry<String, String> entry : featureTypes.entrySet())
+    {
+      if (entry.getValue().equalsIgnoreCase(description))
+      {
+        return entry.getKey();
+      }
+    }
+    System.err.println(
+            "Warning : Unknown Stockholm annotation type: " + description);
+    return null;
+  }
+
   @Override
   public void initData()
   {
@@ -197,7 +266,7 @@ public class StockholmFile extends AlignFile
     String version;
     // String id;
     Hashtable seqAnn = new Hashtable(); // Sequence related annotations
-    LinkedHashMap<String, String> seqs = new LinkedHashMap<String, String>();
+    LinkedHashMap<String, String> seqs = new LinkedHashMap<>();
     Regex p, r, rend, s, x;
     // Temporary line for processing RNA annotation
     // String RNAannot = "";
@@ -219,7 +288,7 @@ public class StockholmFile extends AlignFile
       // logger.debug("Stockholm version: " + version);
     }
 
-    // We define some Regexes here that will be used regularily later
+    // We define some Regexes here that will be used regularly later
     rend = new Regex("^\\s*\\/\\/"); // Find the end of an alignment
     p = new Regex("(\\S+)\\/(\\d+)\\-(\\d+)"); // split sequence id in
     // id/from/to
@@ -232,7 +301,7 @@ public class StockholmFile extends AlignFile
     Regex closeparen = new Regex("(>|\\])", ")");
 
     // Detect if file is RNA by looking for bracket types
-    Regex detectbrackets = new Regex("(<|>|\\[|\\]|\\(|\\))");
+    // Regex detectbrackets = new Regex("(<|>|\\[|\\]|\\(|\\))");
 
     rend.optimize();
     p.optimize();
@@ -366,7 +435,7 @@ public class StockholmFile extends AlignFile
               Hashtable content = (Hashtable) features.remove(type);
 
               // add alignment annotation for this feature
-              String key = type2id(type);
+              String key = descriptionToType(type);
 
               /*
                * have we added annotation rows for this type ?
@@ -624,17 +693,18 @@ public class StockholmFile extends AlignFile
             }
 
             Hashtable content;
-            if (features.containsKey(this.id2type(type)))
+            if (features.containsKey(StockholmFile.typeToDescription(type)))
             {
               // logger.debug("Found content for " + this.id2type(type));
-              content = (Hashtable) features.get(this.id2type(type));
+              content = (Hashtable) features
+                      .get(StockholmFile.typeToDescription(type));
             }
             else
             {
               // logger.debug("Creating new content holder for " +
               // this.id2type(type));
               content = new Hashtable();
-              features.put(this.id2type(type), content);
+              features.put(StockholmFile.typeToDescription(type), content);
             }
             String ns = (String) content.get(ANNOTATION);
 
@@ -658,7 +728,7 @@ public class StockholmFile extends AlignFile
               strucAnn = new Hashtable();
             }
 
-            Vector<AlignmentAnnotation> newStruc = new Vector<AlignmentAnnotation>();
+            Vector<AlignmentAnnotation> newStruc = new Vector<>();
             parseAnnotationRow(newStruc, type, ns);
             for (AlignmentAnnotation alan : newStruc)
             {
@@ -710,7 +780,7 @@ public class StockholmFile extends AlignFile
   private void guessDatabaseFor(Sequence seqO, String dbr, String dbsource)
   {
     DBRefEntry dbrf = null;
-    List<DBRefEntry> dbrs = new ArrayList<DBRefEntry>();
+    List<DBRefEntry> dbrs = new ArrayList<>();
     String seqdb = "Unknown", sdbac = "" + dbr;
     int st = -1, en = -1, p;
     if ((st = sdbac.indexOf("/")) > -1)
@@ -809,10 +879,8 @@ public class StockholmFile extends AlignFile
           Vector<AlignmentAnnotation> annotation, String label,
           String annots)
   {
-    String convert1, convert2 = null;
-
-    // convert1 = OPEN_PAREN.replaceAll(annots);
-    // convert2 = CLOSE_PAREN.replaceAll(convert1);
+    // String convert1 = OPEN_PAREN.replaceAll(annots);
+    // String convert2 = CLOSE_PAREN.replaceAll(convert1);
     // annots = convert2;
 
     String type = label;
@@ -823,7 +891,7 @@ public class StockholmFile extends AlignFile
               : label;
     }
     boolean ss = false, posterior = false;
-    type = id2type(type);
+    type = typeToDescription(type);
     if (type.equalsIgnoreCase("secondary structure"))
     {
       ss = true;
@@ -837,6 +905,10 @@ public class StockholmFile extends AlignFile
     for (int i = 0; i < annots.length(); i++)
     {
       String pos = annots.substring(i, i + 1);
+      if (UNDERSCORE == pos.charAt(0))
+      {
+        pos = " ";
+      }
       Annotation ann;
       ann = new Annotation(pos, "", ' ', 0f); // 0f is 'valid' null - will not
       // be written out
@@ -918,143 +990,123 @@ public class StockholmFile extends AlignFile
   }
 
   @Override
-  public String print(SequenceI[] s, boolean jvSuffix)
+  public String print(final SequenceI[] sequences, boolean jvSuffix)
   {
-    out = new StringBuffer();
+    StringBuilder out = new StringBuilder();
     out.append("# STOCKHOLM 1.0");
     out.append(newline);
 
-    // find max length of id
-    int max = 0;
-    int maxid = 0;
-    int in = 0;
-    Hashtable dataRef = null;
-    while ((in < s.length) && (s[in] != null))
+    int maxIdWidth = 0;
+    for (SequenceI seq : sequences)
     {
-      String tmp = printId(s[in], jvSuffix);
-      max = Math.max(max, s[in].getLength());
-
-      if (tmp.length() > maxid)
-      {
-        maxid = tmp.length();
-      }
-      if (s[in].getDBRefs() != null)
+      if (seq != null)
       {
-        for (int idb = 0; idb < s[in].getDBRefs().length; idb++)
-        {
-          if (dataRef == null)
-          {
-            dataRef = new Hashtable();
-          }
-
-          String datAs1 = s[in].getDBRefs()[idb].getSource().toString()
-                  + " ; "
-                  + s[in].getDBRefs()[idb].getAccessionId().toString();
-          dataRef.put(tmp, datAs1);
-        }
+        String formattedId = printId(seq, jvSuffix);
+        maxIdWidth = Math.max(maxIdWidth, formattedId.length());
       }
-      in++;
     }
-    maxid += 9;
-    int i = 0;
+    maxIdWidth += 9;
 
-    // output database type
-    if (al.getProperties() != null)
+    /*
+     * generic alignment properties
+     */
+    Hashtable props = al.getProperties();
+    if (props != null)
     {
-      if (!al.getProperties().isEmpty())
+      for (Object key : props.keySet())
       {
-        Enumeration key = al.getProperties().keys();
-        Enumeration val = al.getProperties().elements();
-        while (key.hasMoreElements())
-        {
-          out.append("#=GF " + key.nextElement() + " " + val.nextElement());
-          out.append(newline);
-        }
+        out.append(String.format("#=GF %s %s", key.toString(),
+                props.get(key).toString()));
+        out.append(newline);
       }
     }
 
-    // output database accessions
-    if (dataRef != null)
+    /*
+     * output database accessions as #=GS (per sequence annotation)
+     * PFAM or RFAM are output as AC <accession number>
+     * others are output as DR <dbname> ; <accession>
+     */
+    Format formatter = new Format("%-" + (maxIdWidth - 2) + "s");
+    for (SequenceI seq : sequences)
     {
-      Enumeration en = dataRef.keys();
-      while (en.hasMoreElements())
+      if (seq != null)
       {
-        Object idd = en.nextElement();
-        String type = (String) dataRef.remove(idd);
-        out.append(new Format("%-" + (maxid - 2) + "s")
-                .form("#=GS " + idd.toString() + " "));
-        if (type.contains("PFAM") || type.contains("RFAM"))
-        {
-
-          out.append(" AC " + type.substring(type.indexOf(";") + 1));
-        }
-        else
+        DBRefEntry[] dbRefs = seq.getDBRefs();
+        if (dbRefs != null)
         {
-          out.append(" DR " + type + " ");
+          String idField = formatter
+                  .form("#=GS " + printId(seq, jvSuffix) + " ");
+          for (DBRefEntry dbRef : dbRefs)
+          {
+            out.append(idField);
+            printDbRef(out, dbRef);
+          }
         }
-        out.append(newline);
       }
     }
 
-    // output annotations
-    while (i < s.length && s[i] != null)
+    /*
+     * output annotations
+     */
+    for (SequenceI seq : sequences)
     {
-      AlignmentAnnotation[] alAnot = s[i].getAnnotation();
-      if (alAnot != null)
+      if (seq != null)
       {
-        Annotation[] ann;
-        for (int j = 0; j < alAnot.length; j++)
+        AlignmentAnnotation[] alAnot = seq.getAnnotation();
+        if (alAnot != null)
         {
-
-          String key = type2id(alAnot[j].label);
-          boolean isrna = alAnot[j].isValidStruc();
-
-          if (isrna)
-          {
-            // hardwire to secondary structure if there is RNA secondary
-            // structure on the annotation
-            key = "SS";
-          }
-          if (key == null)
+          for (int j = 0; j < alAnot.length; j++)
           {
+            AlignmentAnnotation ann = alAnot[j];
+            String key = descriptionToType(ann.label);
+            boolean isrna = ann.isValidStruc();
+            if (isrna)
+            {
+              /*
+               * output as secondary structure if there is 
+               * RNA secondary structure on the annotation
+               */
+              key = "SS";
+            }
+            if (key == null)
+            {
+              continue;
+            }
 
-            continue;
-          }
-
-          // out.append("#=GR ");
-          out.append(new Format("%-" + maxid + "s").form(
-                  "#=GR " + printId(s[i], jvSuffix) + " " + key + " "));
-          ann = alAnot[j].annotations;
-          String seq = "";
-          for (int k = 0; k < ann.length; k++)
-          {
-            seq += outputCharacter(key, k, isrna, ann, s[i]);
+            out.append(new Format("%-" + maxIdWidth + "s").form(
+                    "#=GR " + printId(seq, jvSuffix) + " " + key + " "));
+            Annotation[] anns = ann.annotations;
+            StringBuilder seqString = new StringBuilder();
+            for (int k = 0; k < anns.length; k++)
+            {
+              seqString
+                      .append(getAnnotationCharacter(key, k, anns[k], seq));
+            }
+            out.append(seqString.toString());
+            out.append(newline);
           }
-          out.append(seq);
-          out.append(newline);
         }
-      }
 
-      out.append(new Format("%-" + maxid + "s")
-              .form(printId(s[i], jvSuffix) + " "));
-      out.append(s[i].getSequenceAsString());
-      out.append(newline);
-      i++;
+        out.append(new Format("%-" + maxIdWidth + "s")
+                .form(printId(seq, jvSuffix) + " "));
+        out.append(seq.getSequenceAsString());
+        out.append(newline);
+      }
     }
 
-    // alignment annotation
-    AlignmentAnnotation aa;
+    /*
+     * output alignment annotation (but not auto-calculated or sequence-related)
+     */
     if (al.getAlignmentAnnotation() != null)
     {
       for (int ia = 0; ia < al.getAlignmentAnnotation().length; ia++)
       {
-        aa = al.getAlignmentAnnotation()[ia];
+        AlignmentAnnotation aa = al.getAlignmentAnnotation()[ia];
         if (aa.autoCalculated || !aa.visible || aa.sequenceRef != null)
         {
           continue;
         }
-        String seq = "";
-        String label;
+        String label = aa.label;
         String key = "";
         if (aa.label.equals("seq"))
         {
@@ -1062,30 +1114,28 @@ public class StockholmFile extends AlignFile
         }
         else
         {
-          key = type2id(aa.label.toLowerCase());
-          if (key == null)
+          key = descriptionToType(aa.label);
+          if ("RF".equals(key))
           {
-            label = aa.label;
+            label = key;
           }
-          else
+          else if (key != null)
           {
             label = key + "_cons";
           }
         }
-        if (label == null)
-        {
-          label = aa.label;
-        }
         label = label.replace(" ", "_");
 
         out.append(
-                new Format("%-" + maxid + "s").form("#=GC " + label + " "));
-        boolean isrna = aa.isValidStruc();
+                new Format("%-" + maxIdWidth + "s")
+                        .form("#=GC " + label + " "));
+        StringBuilder sb = new StringBuilder(aa.annotations.length);
         for (int j = 0; j < aa.annotations.length; j++)
         {
-          seq += outputCharacter(key, j, isrna, aa.annotations, null);
+          sb.append(
+                  getAnnotationCharacter(key, j, aa.annotations[j], null));
         }
-        out.append(seq);
+        out.append(sb.toString());
         out.append(newline);
       }
     }
@@ -1097,20 +1147,40 @@ public class StockholmFile extends AlignFile
   }
 
   /**
-   * add an annotation character to the output row
+   * A helper method that appends a formatted dbref to the output buffer
+   * 
+   * @param out
+   * @param dbRef
+   */
+  protected void printDbRef(StringBuilder out, DBRefEntry dbRef)
+  {
+    String db = dbRef.getSource();
+    String acc = dbRef.getAccessionId();
+    if (DBRefSource.PFAM.equalsIgnoreCase(db)
+            || DBRefSource.RFAM.equalsIgnoreCase(db))
+    {
+      out.append(" AC " + acc);
+    }
+    else
+    {
+      out.append(" DR " + db + " ; " + acc);
+    }
+    out.append(newline);
+  }
+
+  /**
+   * Returns an annotation character to add to the output row
    * 
    * @param seq
    * @param key
    * @param k
-   * @param isrna
    * @param ann
    * @param sequenceI
    */
-  private char outputCharacter(String key, int k, boolean isrna,
-          Annotation[] ann, SequenceI sequenceI)
+  static char getAnnotationCharacter(String key, int k, Annotation annot,
+          SequenceI sequenceI)
   {
     char seq = ' ';
-    Annotation annot = ann[k];
     String ch = (annot == null)
             ? ((sequenceI == null) ? "-"
                     : Character.toString(sequenceI.getCharAt(k)))
@@ -1119,8 +1189,8 @@ public class StockholmFile extends AlignFile
     {
       if (annot == null)
       {
-        // sensible gap character
-        return ' ';
+        // Stockholm format requires underscore, not space
+        return UNDERSCORE;
       }
       else
       {
@@ -1147,77 +1217,6 @@ public class StockholmFile extends AlignFile
     return seq;
   }
 
-  public String print()
-  {
-    out = new StringBuffer();
-    out.append("# STOCKHOLM 1.0");
-    out.append(newline);
-    print(getSeqsAsArray(), false);
-
-    out.append("//");
-    out.append(newline);
-    return out.toString();
-  }
-
-  private static Hashtable typeIds = null;
-
-  static
-  {
-    if (typeIds == null)
-    {
-      typeIds = new Hashtable();
-      typeIds.put("SS", "Secondary Structure");
-      typeIds.put("SA", "Surface Accessibility");
-      typeIds.put("TM", "transmembrane");
-      typeIds.put("PP", "Posterior Probability");
-      typeIds.put("LI", "ligand binding");
-      typeIds.put("AS", "active site");
-      typeIds.put("IN", "intron");
-      typeIds.put("IR", "interacting residue");
-      typeIds.put("AC", "accession");
-      typeIds.put("OS", "organism");
-      typeIds.put("CL", "class");
-      typeIds.put("DE", "description");
-      typeIds.put("DR", "reference");
-      typeIds.put("LO", "look");
-      typeIds.put("RF", "Reference Positions");
-
-    }
-  }
-
-  protected static String id2type(String id)
-  {
-    if (typeIds.containsKey(id))
-    {
-      return (String) typeIds.get(id);
-    }
-    System.err.println(
-            "Warning : Unknown Stockholm annotation type code " + id);
-    return id;
-  }
-
-  protected static String type2id(String type)
-  {
-    String key = null;
-    Enumeration e = typeIds.keys();
-    while (e.hasMoreElements())
-    {
-      Object ll = e.nextElement();
-      if (typeIds.get(ll).toString().equalsIgnoreCase(type))
-      {
-        key = (String) ll;
-        break;
-      }
-    }
-    if (key != null)
-    {
-      return key;
-    }
-    System.err.println(
-            "Warning : Unknown Stockholm annotation type: " + type);
-    return key;
-  }
-
   /**
    * make a friendly ID string.
    * 
index 1cf482d..8226cee 100755 (executable)
@@ -25,6 +25,8 @@ import jalview.api.SplitContainerI;
 import jalview.bin.Cache;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.Preferences;
+import jalview.hmmer.HmmerCommand;
+import jalview.io.FileFormatException;
 import jalview.io.FileFormats;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
@@ -40,6 +42,7 @@ import java.awt.event.FocusEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -67,6 +70,28 @@ public class GAlignFrame extends JInternalFrame
 
   protected JMenu webService = new JMenu();
 
+  protected JMenu hmmerMenu = new JMenu();
+
+  protected JMenu hmmAlign = new JMenu();
+
+  protected JMenuItem hmmAlignRun = new JMenuItem();
+
+  protected JMenuItem hmmAlignSettings = new JMenuItem();
+
+  protected JMenu hmmSearch = new JMenu();
+
+  protected JMenuItem hmmSearchRun = new JMenuItem();
+
+  protected JMenuItem hmmSearchSettings = new JMenuItem();
+
+  protected JMenuItem addDatabase = new JMenuItem();
+
+  protected JMenu hmmBuild = new JMenu();
+
+  protected JMenuItem hmmBuildRun = new JMenuItem();
+
+  protected JMenuItem hmmBuildSettings = new JMenuItem();
+
   protected JMenuItem webServiceNoServices;
 
   protected JCheckBoxMenuItem viewBoxesMenuItem = new JCheckBoxMenuItem();
@@ -195,13 +220,19 @@ public class GAlignFrame extends JInternalFrame
 
   protected JCheckBoxMenuItem normaliseSequenceLogo = new JCheckBoxMenuItem();
 
+  protected JCheckBoxMenuItem showInformationHistogram = new JCheckBoxMenuItem();
+
+  protected JCheckBoxMenuItem showHMMSequenceLogo = new JCheckBoxMenuItem();
+
+  protected JCheckBoxMenuItem normaliseHMMSequenceLogo = new JCheckBoxMenuItem();
+
   protected JCheckBoxMenuItem applyAutoAnnotationSettings = new JCheckBoxMenuItem();
 
   private SequenceAnnotationOrder annotationSortOrder;
 
   private boolean showAutoCalculatedAbove = false;
 
-  private Map<KeyStroke, JMenuItem> accelerators = new HashMap<KeyStroke, JMenuItem>();
+  private Map<KeyStroke, JMenuItem> accelerators = new HashMap<>();
 
   private SplitContainerI splitFrame;
 
@@ -249,7 +280,8 @@ public class GAlignFrame extends JInternalFrame
   private void jbInit() throws Exception
   {
     initColourMenu();
-
+    initHMMERMenu();
+  
     JMenuItem saveAs = new JMenuItem(
             MessageManager.getString("action.save_as"));
     ActionListener al = new ActionListener()
@@ -260,14 +292,14 @@ public class GAlignFrame extends JInternalFrame
         saveAs_actionPerformed(e);
       }
     };
-
+  
     // FIXME getDefaultToolkit throws an exception in Headless mode
     KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S,
             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()
                     | KeyEvent.SHIFT_MASK,
             false);
     addMenuActionAndAccelerator(keyStroke, saveAs, al);
-
+  
     closeMenuItem.setText(MessageManager.getString("action.close"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_W,
             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
@@ -280,7 +312,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, closeMenuItem, al);
-
+  
     JMenu editMenu = new JMenu(MessageManager.getString("action.edit"));
     JMenu viewMenu = new JMenu(MessageManager.getString("action.view"));
     JMenu annotationsMenu = new JMenu(
@@ -290,6 +322,20 @@ public class GAlignFrame extends JInternalFrame
     JMenu calculateMenu = new JMenu(
             MessageManager.getString("action.calculate"));
     webService.setText(MessageManager.getString("action.web_service"));
+    hmmerMenu.setText(MessageManager.getString("action.hmmer"));
+    hmmerMenu.setEnabled(HmmerCommand.isHmmerAvailable());
+    hmmerMenu.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmerMenu_actionPerformed(e);
+      }
+    });
+    hmmerMenu.add(hmmBuild);
+    hmmerMenu.add(hmmAlign);
+    hmmerMenu.add(hmmSearch);
+
     JMenuItem selectAllSequenceMenuItem = new JMenuItem(
             MessageManager.getString("action.select_all"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A,
@@ -303,7 +349,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, selectAllSequenceMenuItem, al);
-
+  
     JMenuItem deselectAllSequenceMenuItem = new JMenuItem(
             MessageManager.getString("action.deselect_all"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
@@ -316,7 +362,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, deselectAllSequenceMenuItem, al);
-
+  
     JMenuItem invertSequenceMenuItem = new JMenuItem(
             MessageManager.getString("action.invert_sequence_selection"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I,
@@ -330,7 +376,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, invertSequenceMenuItem, al);
-
+  
     JMenuItem grpsFromSelection = new JMenuItem(
             MessageManager.getString("action.make_groups_selection"));
     grpsFromSelection.addActionListener(new ActionListener()
@@ -366,7 +412,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, remove2LeftMenuItem, al);
-
+  
     JMenuItem remove2RightMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_right"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_R,
@@ -380,7 +426,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, remove2RightMenuItem, al);
-
+  
     JMenuItem removeGappedColumnMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_empty_columns"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E,
@@ -394,7 +440,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, removeGappedColumnMenuItem, al);
-
+  
     JMenuItem removeAllGapsMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_all_gaps"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_E,
@@ -410,7 +456,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, removeAllGapsMenuItem, al);
-
+  
     JMenuItem justifyLeftMenuItem = new JMenuItem(
             MessageManager.getString("action.left_justify_alignment"));
     justifyLeftMenuItem.addActionListener(new ActionListener()
@@ -502,7 +548,7 @@ public class GAlignFrame extends JInternalFrame
         sortGroupMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem removeRedundancyMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_redundancy"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_D,
@@ -516,7 +562,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, removeRedundancyMenuItem, al);
-
+  
     JMenuItem pairwiseAlignmentMenuItem = new JMenuItem(
             MessageManager.getString("action.pairwise_alignment"));
     pairwiseAlignmentMenuItem.addActionListener(new ActionListener()
@@ -527,16 +573,18 @@ public class GAlignFrame extends JInternalFrame
         pairwiseAlignmentMenuItem_actionPerformed(e);
       }
     });
-
+  
     this.getContentPane().setLayout(new BorderLayout());
     alignFrameMenuBar.setFont(new java.awt.Font("Verdana", 0, 11));
     statusBar.setBackground(Color.white);
     statusBar.setFont(new java.awt.Font("Verdana", 0, 11));
     statusBar.setBorder(BorderFactory.createLineBorder(Color.black));
     statusBar.setText(MessageManager.getString("label.status_bar"));
+
     outputTextboxMenu
             .setText(MessageManager.getString("label.out_to_textbox"));
 
+
     annotationPanelMenuItem.setActionCommand("");
     annotationPanelMenuItem
             .setText(MessageManager.getString("label.show_annotations"));
@@ -604,6 +652,7 @@ public class GAlignFrame extends JInternalFrame
     final JCheckBoxMenuItem sortAnnByLabel = new JCheckBoxMenuItem(
             MessageManager.getString("label.sort_annotations_by_label"));
 
+
     sortAnnBySequence.setSelected(
             sortAnnotationsBy == SequenceAnnotationOrder.SEQUENCE_AND_LABEL);
     sortAnnBySequence.addActionListener(new ActionListener()
@@ -644,7 +693,7 @@ public class GAlignFrame extends JInternalFrame
         colourTextMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem htmlMenuItem = new JMenuItem(
             MessageManager.getString("label.html"));
     htmlMenuItem.addActionListener(new ActionListener()
@@ -655,7 +704,7 @@ public class GAlignFrame extends JInternalFrame
         htmlMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem createBioJS = new JMenuItem(
             MessageManager.getString("label.biojs_html_export"));
     createBioJS.addActionListener(new java.awt.event.ActionListener()
@@ -666,7 +715,7 @@ public class GAlignFrame extends JInternalFrame
         bioJSMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem overviewMenuItem = new JMenuItem(
             MessageManager.getString("label.overview_window"));
     overviewMenuItem.addActionListener(new ActionListener()
@@ -677,7 +726,7 @@ public class GAlignFrame extends JInternalFrame
         overviewMenuItem_actionPerformed(e);
       }
     });
-
+  
     undoMenuItem.setEnabled(false);
     undoMenuItem.setText(MessageManager.getString("action.undo"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
@@ -691,7 +740,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, undoMenuItem, al);
-
+  
     redoMenuItem.setEnabled(false);
     redoMenuItem.setText(MessageManager.getString("action.redo"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Y,
@@ -705,7 +754,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, redoMenuItem, al);
-
+  
     wrapMenuItem.setText(MessageManager.getString("label.wrap"));
     wrapMenuItem.addActionListener(new ActionListener()
     {
@@ -715,7 +764,7 @@ public class GAlignFrame extends JInternalFrame
         wrapMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem printMenuItem = new JMenuItem(
             MessageManager.getString("action.print"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_P,
@@ -729,7 +778,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, printMenuItem, al);
-
+  
     renderGapsMenuItem
             .setText(MessageManager.getString("action.show_gaps"));
     renderGapsMenuItem.setState(true);
@@ -741,7 +790,7 @@ public class GAlignFrame extends JInternalFrame
         renderGapsMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem findMenuItem = new JMenuItem(
             MessageManager.getString("action.find"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_F,
@@ -760,6 +809,7 @@ public class GAlignFrame extends JInternalFrame
 
     showSeqFeatures.setText(
             MessageManager.getString("label.show_sequence_features"));
+
     showSeqFeatures.addActionListener(new ActionListener()
     {
       @Override
@@ -778,86 +828,86 @@ public class GAlignFrame extends JInternalFrame
             .setText(MessageManager.getString("label.show_database_refs"));
     showDbRefsMenuitem.addActionListener(new ActionListener()
     {
-
+  
       @Override
       public void actionPerformed(ActionEvent e)
       {
         showDbRefs_actionPerformed(e);
       }
-
+  
     });
     showNpFeatsMenuitem.setText(
             MessageManager.getString("label.show_non_positional_features"));
     showNpFeatsMenuitem.addActionListener(new ActionListener()
     {
-
+  
       @Override
       public void actionPerformed(ActionEvent e)
       {
         showNpFeats_actionPerformed(e);
       }
-
+  
     });
     showGroupConservation
             .setText(MessageManager.getString("label.group_conservation"));
     showGroupConservation.addActionListener(new ActionListener()
     {
-
+  
       @Override
       public void actionPerformed(ActionEvent e)
       {
         showGroupConservation_actionPerformed(e);
       }
-
+  
     });
 
     showGroupConsensus
             .setText(MessageManager.getString("label.group_consensus"));
     showGroupConsensus.addActionListener(new ActionListener()
     {
-
+  
       @Override
       public void actionPerformed(ActionEvent e)
       {
         showGroupConsensus_actionPerformed(e);
       }
-
+  
     });
     showConsensusHistogram.setText(
             MessageManager.getString("label.show_consensus_histogram"));
     showConsensusHistogram.addActionListener(new ActionListener()
     {
-
+  
       @Override
       public void actionPerformed(ActionEvent e)
       {
         showConsensusHistogram_actionPerformed(e);
       }
-
+  
     });
     showSequenceLogo
             .setText(MessageManager.getString("label.show_consensus_logo"));
     showSequenceLogo.addActionListener(new ActionListener()
     {
-
+  
       @Override
       public void actionPerformed(ActionEvent e)
       {
         showSequenceLogo_actionPerformed(e);
       }
-
+  
     });
     normaliseSequenceLogo
             .setText(MessageManager.getString("label.norm_consensus_logo"));
     normaliseSequenceLogo.addActionListener(new ActionListener()
     {
-
+  
       @Override
       public void actionPerformed(ActionEvent e)
       {
         normaliseSequenceLogo_actionPerformed(e);
       }
-
+  
     });
     applyAutoAnnotationSettings
             .setText(MessageManager.getString("label.apply_all_groups"));
@@ -871,7 +921,7 @@ public class GAlignFrame extends JInternalFrame
         applyAutoAnnotationSettings_actionPerformed(e);
       }
     });
-
+  
     ButtonGroup buttonGroup = new ButtonGroup();
     final JRadioButtonMenuItem showAutoFirst = new JRadioButtonMenuItem(
             MessageManager.getString("label.show_first"));
@@ -902,7 +952,7 @@ public class GAlignFrame extends JInternalFrame
         sortAnnotations_actionPerformed();
       }
     });
-
+  
     JMenuItem deleteGroups = new JMenuItem(
             MessageManager.getString("action.undefine_groups"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_U,
@@ -916,7 +966,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, deleteGroups, al);
-
+  
     JMenuItem annotationColumn = new JMenuItem(
             MessageManager.getString("action.select_by_annotation"));
     annotationColumn.addActionListener(new ActionListener()
@@ -927,7 +977,7 @@ public class GAlignFrame extends JInternalFrame
         annotationColumn_actionPerformed(e);
       }
     });
-
+  
     JMenuItem createGroup = new JMenuItem(
             MessageManager.getString("action.create_group"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G,
@@ -941,7 +991,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, createGroup, al);
-
+  
     JMenuItem unGroup = new JMenuItem(
             MessageManager.getString("action.remove_group"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G,
@@ -957,7 +1007,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, unGroup, al);
-
+  
     copy.setText(MessageManager.getString("action.copy"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_C,
             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
@@ -971,7 +1021,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, copy, al);
-
+  
     cut.setText(MessageManager.getString("action.cut"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_X,
             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
@@ -984,7 +1034,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, cut, al);
-
+  
     JMenuItem delete = new JMenuItem(
             MessageManager.getString("action.delete"));
     delete.addActionListener(new ActionListener()
@@ -995,7 +1045,7 @@ public class GAlignFrame extends JInternalFrame
         delete_actionPerformed(e);
       }
     });
-
+  
     pasteMenu.setText(MessageManager.getString("action.paste"));
     JMenuItem pasteNew = new JMenuItem(
             MessageManager.getString("label.to_new_alignment"));
@@ -1008,11 +1058,18 @@ public class GAlignFrame extends JInternalFrame
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        pasteNew_actionPerformed(e);
+        try
+        {
+          pasteNew_actionPerformed(e);
+        } catch (IOException | InterruptedException e1)
+        {
+          // TODO Auto-generated catch block
+          e1.printStackTrace();
+        }
       }
     };
     addMenuActionAndAccelerator(keyStroke, pasteNew, al);
-
+  
     JMenuItem pasteThis = new JMenuItem(
             MessageManager.getString("label.to_this_alignment"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_V,
@@ -1022,11 +1079,18 @@ public class GAlignFrame extends JInternalFrame
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        pasteThis_actionPerformed(e);
+        try
+        {
+          pasteThis_actionPerformed(e);
+        } catch (IOException | InterruptedException e1)
+        {
+          // TODO Auto-generated catch block
+          e1.printStackTrace();
+        }
       }
     };
     addMenuActionAndAccelerator(keyStroke, pasteThis, al);
-
+  
     JMenuItem createPNG = new JMenuItem("PNG");
     createPNG.addActionListener(new ActionListener()
     {
@@ -1038,7 +1102,6 @@ public class GAlignFrame extends JInternalFrame
     });
     createPNG.setActionCommand(
             MessageManager.getString("label.save_png_image"));
-
     JMenuItem font = new JMenuItem(MessageManager.getString("action.font"));
     font.addActionListener(new ActionListener()
     {
@@ -1068,7 +1131,7 @@ public class GAlignFrame extends JInternalFrame
         createEPS(null);
       }
     });
-
+  
     JMenuItem createSVG = new JMenuItem("SVG");
     createSVG.addActionListener(new ActionListener()
     {
@@ -1078,7 +1141,7 @@ public class GAlignFrame extends JInternalFrame
         createSVG(null);
       }
     });
-
+  
     JMenuItem loadTreeMenuItem = new JMenuItem(
             MessageManager.getString("label.load_associated_tree"));
     loadTreeMenuItem.setActionCommand(
@@ -1091,7 +1154,7 @@ public class GAlignFrame extends JInternalFrame
         loadTreeMenuItem_actionPerformed(e);
       }
     });
-
+  
     scaleAbove.setVisible(false);
     scaleAbove.setText(MessageManager.getString("action.scale_above"));
     scaleAbove.addActionListener(new ActionListener()
@@ -1142,15 +1205,15 @@ public class GAlignFrame extends JInternalFrame
             .setText(MessageManager.getString("label.automatic_scrolling"));
     followHighlightMenuItem.addActionListener(new ActionListener()
     {
-
+  
       @Override
       public void actionPerformed(ActionEvent e)
       {
         followHighlight_actionPerformed();
       }
-
+  
     });
-
+  
     sortByTreeMenu
             .setText(MessageManager.getString("action.by_tree_order"));
     sort.setText(MessageManager.getString("action.sort"));
@@ -1161,12 +1224,12 @@ public class GAlignFrame extends JInternalFrame
       {
         buildTreeSortMenu();
       }
-
+  
       @Override
       public void menuDeselected(MenuEvent e)
       {
       }
-
+  
       @Override
       public void menuCanceled(MenuEvent e)
       {
@@ -1177,17 +1240,17 @@ public class GAlignFrame extends JInternalFrame
     sort.add(sortByAnnotScore);
     sort.addMenuListener(new javax.swing.event.MenuListener()
     {
-
+  
       @Override
       public void menuCanceled(MenuEvent e)
       {
       }
-
+  
       @Override
       public void menuDeselected(MenuEvent e)
       {
       }
-
+  
       @Override
       public void menuSelected(MenuEvent e)
       {
@@ -1250,7 +1313,7 @@ public class GAlignFrame extends JInternalFrame
         showReverse_actionPerformed(true);
       }
     });
-
+  
     JMenuItem extractScores = new JMenuItem(
             MessageManager.getString("label.extract_scores"));
     extractScores.addActionListener(new ActionListener()
@@ -1263,10 +1326,10 @@ public class GAlignFrame extends JInternalFrame
     });
     extractScores.setVisible(true);
     // JBPNote: TODO: make gui for regex based score extraction
-
+  
     // for show products actions see AlignFrame.canShowProducts
     showProducts.setText(MessageManager.getString("label.get_cross_refs"));
-
+  
     runGroovy.setText(MessageManager.getString("label.run_groovy"));
     runGroovy.setToolTipText(
             MessageManager.getString("label.run_groovy_tip"));
@@ -1278,7 +1341,7 @@ public class GAlignFrame extends JInternalFrame
         runGroovy_actionPerformed();
       }
     });
-
+  
     JMenuItem openFeatureSettings = new JMenuItem(
             MessageManager.getString("action.feature_settings"));
     openFeatureSettings.addActionListener(new ActionListener()
@@ -1299,7 +1362,7 @@ public class GAlignFrame extends JInternalFrame
         fetchSequence_actionPerformed(e);
       }
     });
-
+  
     JMenuItem associatedData = new JMenuItem(
             MessageManager.getString("label.load_features_annotations"));
     associatedData.addActionListener(new ActionListener()
@@ -1307,7 +1370,14 @@ public class GAlignFrame extends JInternalFrame
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        associatedData_actionPerformed(e);
+        try
+        {
+          associatedData_actionPerformed(e);
+        } catch (IOException | InterruptedException e1)
+        {
+          // TODO Auto-generated catch block
+          e1.printStackTrace();
+        }
       }
     });
     loadVcf = new JMenuItem(MessageManager.getString("label.load_vcf_file"));
@@ -1361,7 +1431,7 @@ public class GAlignFrame extends JInternalFrame
         listenToViewSelections_actionPerformed(e);
       }
     });
-
+  
     JMenu addSequenceMenu = new JMenu(
             MessageManager.getString("label.add_sequences"));
     JMenuItem addFromFile = new JMenuItem(
@@ -1507,7 +1577,7 @@ public class GAlignFrame extends JInternalFrame
         hiddenMarkers_actionPerformed(e);
       }
     });
-
+  
     JMenuItem invertColSel = new JMenuItem(
             MessageManager.getString("action.invert_column_selection"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_I,
@@ -1523,7 +1593,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, invertColSel, al);
-
+  
     showComplementMenuItem.setVisible(false);
     showComplementMenuItem.addActionListener(new ActionListener()
     {
@@ -1533,7 +1603,7 @@ public class GAlignFrame extends JInternalFrame
         showComplement_actionPerformed(showComplementMenuItem.getState());
       }
     });
-
+  
     tabbedPane.addChangeListener(new javax.swing.event.ChangeListener()
     {
       @Override
@@ -1554,7 +1624,7 @@ public class GAlignFrame extends JInternalFrame
           tabbedPane_mousePressed(e);
         }
       }
-
+  
       @Override
       public void mouseReleased(MouseEvent e)
       {
@@ -1572,7 +1642,7 @@ public class GAlignFrame extends JInternalFrame
         tabbedPane_focusGained(e);
       }
     });
-
+  
     JMenuItem save = new JMenuItem(MessageManager.getString("action.save"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S,
             Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(), false);
@@ -1585,7 +1655,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, save, al);
-
+  
     reload.setEnabled(false);
     reload.setText(MessageManager.getString("action.reload"));
     reload.addActionListener(new ActionListener()
@@ -1596,7 +1666,7 @@ public class GAlignFrame extends JInternalFrame
         reload_actionPerformed(e);
       }
     });
-
+  
     JMenuItem newView = new JMenuItem(
             MessageManager.getString("action.new_view"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_T,
@@ -1610,11 +1680,11 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, newView, al);
-
+  
     tabbedPane.setToolTipText("<html><i>"
             + MessageManager.getString("label.rename_tab_eXpand_reGroup")
             + "</i></html>");
-
+  
     formatMenu.setText(MessageManager.getString("action.format"));
     JMenu selectMenu = new JMenu(MessageManager.getString("action.select"));
 
@@ -1628,7 +1698,7 @@ public class GAlignFrame extends JInternalFrame
         idRightAlign_actionPerformed(e);
       }
     });
-
+  
     gatherViews.setEnabled(false);
     gatherViews.setText(MessageManager.getString("action.gather_views"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G, 0, false);
@@ -1641,7 +1711,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, gatherViews, al);
-
+  
     expandViews.setEnabled(false);
     expandViews.setText(MessageManager.getString("action.expand_views"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_X, 0, false);
@@ -1654,7 +1724,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, expandViews, al);
-
+  
     JMenuItem pageSetup = new JMenuItem(
             MessageManager.getString("action.page_setup"));
     pageSetup.addActionListener(new ActionListener()
@@ -1687,12 +1757,87 @@ public class GAlignFrame extends JInternalFrame
         selectHighlightedColumns_actionPerformed(actionEvent);
       }
     };
+    hmmBuildRun.setText(MessageManager.formatMessage(
+            "label.action_with_default_settings", "hmmbuild"));
+    hmmBuildRun.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmBuild_actionPerformed(true);
+      }
+    });
+    hmmBuildSettings.setText(
+            MessageManager.getString("label.edit_settings_and_run"));
+    hmmBuildSettings.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmBuild_actionPerformed(false);
+      }
+    });
+    hmmAlignRun.setText(MessageManager.formatMessage(
+            "label.action_with_default_settings", "hmmalign"));
+    hmmAlignRun.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmAlign_actionPerformed(true);
+      }
+    });
+    hmmAlignSettings.setText(
+            MessageManager.getString("label.edit_settings_and_run"));
+    hmmAlignSettings.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmAlign_actionPerformed(false);
+      }
+    });
+    hmmSearchRun.setText(MessageManager.formatMessage(
+            "label.action_with_default_settings", "hmmsearch"));
+    hmmSearchRun.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmSearch_actionPerformed(true);
+      }
+    });
+    hmmSearchSettings.setText(
+            MessageManager.getString("label.edit_settings_and_run"));
+    hmmSearchSettings.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmSearch_actionPerformed(false);
+      }
+    });
+    addDatabase.setText(MessageManager.getString("label.add_database"));
+    addDatabase.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        try
+        {
+          addDatabase_actionPerformed();
+        } catch (IOException e1)
+        {
+          e1.printStackTrace();
+        }
+      }
+    });
     selectHighlighted.addActionListener(al);
     JMenu tooltipSettingsMenu = new JMenu(
             MessageManager.getString("label.sequence_id_tooltip"));
     JMenu autoAnnMenu = new JMenu(
             MessageManager.getString("label.autocalculated_annotation"));
-
+  
     JMenu exportImageMenu = new JMenu(
             MessageManager.getString("label.export_image"));
     JMenu fileMenu = new JMenu(MessageManager.getString("action.file"));
@@ -1705,7 +1850,8 @@ public class GAlignFrame extends JInternalFrame
     alignFrameMenuBar.add(colourMenu);
     alignFrameMenuBar.add(calculateMenu);
     alignFrameMenuBar.add(webService);
-
+    alignFrameMenuBar.add(hmmerMenu);
+  
     fileMenu.add(fetchSequence);
     fileMenu.add(addSequenceMenu);
     fileMenu.add(reload);
@@ -1725,7 +1871,7 @@ public class GAlignFrame extends JInternalFrame
     fileMenu.add(loadVcf);
     fileMenu.addSeparator();
     fileMenu.add(closeMenuItem);
-
+  
     pasteMenu.add(pasteNew);
     pasteMenu.add(pasteThis);
     editMenu.add(undoMenuItem);
@@ -1747,7 +1893,7 @@ public class GAlignFrame extends JInternalFrame
     // editMenu.add(justifyRightMenuItem);
     // editMenu.addSeparator();
     editMenu.add(padGapsMenuitem);
-
+  
     showMenu.add(showAllColumns);
     showMenu.add(showAllSeqs);
     showMenu.add(showAllhidden);
@@ -1775,7 +1921,7 @@ public class GAlignFrame extends JInternalFrame
     viewMenu.add(alignmentProperties);
     viewMenu.addSeparator();
     viewMenu.add(overviewMenuItem);
-
+  
     annotationsMenu.add(annotationPanelMenuItem);
     annotationsMenu.addSeparator();
     annotationsMenu.add(showAllAlAnnotations);
@@ -1819,7 +1965,7 @@ public class GAlignFrame extends JInternalFrame
     calculateMenu.add(extractScores);
     calculateMenu.addSeparator();
     calculateMenu.add(runGroovy);
-
+  
     webServiceNoServices = new JMenuItem(
             MessageManager.getString("label.no_services"));
     webService.add(webServiceNoServices);
@@ -1834,7 +1980,7 @@ public class GAlignFrame extends JInternalFrame
     this.getContentPane().add(statusPanel, java.awt.BorderLayout.SOUTH);
     statusPanel.add(statusBar, null);
     this.getContentPane().add(tabbedPane, java.awt.BorderLayout.CENTER);
-
+  
     formatMenu.add(font);
     formatMenu.addSeparator();
     formatMenu.add(wrapMenuItem);
@@ -1868,6 +2014,42 @@ public class GAlignFrame extends JInternalFrame
     // selectMenu.add(listenToViewSelections);
   }
 
+  public void hmmerMenu_actionPerformed(ActionEvent e)
+  {
+
+  }
+
+  /**
+   * Constructs the entries on the HMMER menu (does not add them to the menu).
+   */
+  protected void initHMMERMenu()
+  {
+    hmmAlign = new JMenu(MessageManager.getString("label.hmmalign"));
+    hmmAlignSettings = new JMenuItem(
+            MessageManager.getString("label.edit_settings_and_run"));
+    hmmAlignRun = new JMenuItem(MessageManager.formatMessage(
+            "label.action_with_default_settings", "hmmalign"));
+    hmmAlign.add(hmmAlignSettings);
+    hmmAlign.add(hmmAlignRun);
+    hmmBuild = new JMenu(MessageManager.getString("label.hmmbuild"));
+    hmmBuildSettings = new JMenuItem(
+            MessageManager.getString("label.edit_settings_and_run"));
+    hmmBuildRun = new JMenuItem(MessageManager.formatMessage(
+            "label.action_with_default_settings", "hmmbuild"));
+    hmmBuild.add(hmmBuildSettings);
+    hmmBuild.add(hmmBuildRun);
+    hmmSearch = new JMenu(MessageManager.getString("label.hmmsearch"));
+    hmmSearchSettings = new JMenuItem(
+            MessageManager.getString("label.edit_settings_and_run"));
+    hmmSearchRun = new JMenuItem(MessageManager.formatMessage(
+            "label.action_with_default_settings", "hmmsearch"));
+    addDatabase = new JMenuItem(
+            MessageManager.getString("label.add_database"));
+    hmmSearch.add(hmmSearchSettings);
+    hmmSearch.add(hmmSearchRun);
+    hmmSearch.add(addDatabase);
+  }
+
   protected void loadVcf_actionPerformed()
   {
   }
@@ -2343,10 +2525,12 @@ public class GAlignFrame extends JInternalFrame
   }
 
   protected void pasteNew_actionPerformed(ActionEvent e)
+          throws IOException, InterruptedException
   {
   }
 
   protected void pasteThis_actionPerformed(ActionEvent e)
+          throws IOException, InterruptedException
   {
   }
 
@@ -2354,6 +2538,23 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
+  protected void hmmBuild_actionPerformed(boolean withDefaults)
+  {
+  }
+
+  protected void hmmSearch_actionPerformed(boolean withDefaults)
+  {
+  }
+
+  protected void addDatabase_actionPerformed()
+          throws FileFormatException, IOException
+  {
+  }
+
+  protected void hmmAlign_actionPerformed(boolean withDefaults)
+  {
+  }
+
   public void createPNG(java.io.File f)
   {
   }
@@ -2469,6 +2670,7 @@ public class GAlignFrame extends JInternalFrame
   }
 
   public void associatedData_actionPerformed(ActionEvent e)
+          throws IOException, InterruptedException
   {
 
   }
index 1ca0802..380db74 100755 (executable)
@@ -26,6 +26,7 @@ import jalview.fts.service.pdb.PDBFTSRestClient;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.StructureViewer.ViewerType;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -40,18 +41,20 @@ import java.awt.Insets;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.awt.event.FocusEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 
+import javax.swing.AbstractButton;
 import javax.swing.AbstractCellEditor;
 import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
 import javax.swing.ButtonGroup;
 import javax.swing.DefaultListCellRenderer;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
+import javax.swing.JComponent;
 import javax.swing.JFileChooser;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
@@ -71,6 +74,8 @@ import javax.swing.event.ChangeListener;
 import javax.swing.table.TableCellEditor;
 import javax.swing.table.TableCellRenderer;
 
+import net.miginfocom.swing.MigLayout;
+
 /**
  * Base class for the Preferences panel.
  * 
@@ -142,10 +147,15 @@ public class GPreferences extends JPanel
 
   protected JCheckBox showConsensLogo = new JCheckBox();
 
+  protected JCheckBox showInformationHistogram = new JCheckBox();
+
+  protected JCheckBox showHMMLogo = new JCheckBox();
+
   protected JCheckBox showDbRefTooltip = new JCheckBox();
 
   protected JCheckBox showNpTooltip = new JCheckBox();
 
+
   /*
    * Structure tab and components
    */
@@ -265,6 +275,23 @@ public class GPreferences extends JPanel
   protected JCheckBox sortByTree = new JCheckBox();
 
   /*
+   * hmmer tab and components
+   */
+  protected JPanel hmmerTab;
+
+  protected JCheckBox hmmrTrimTermini;
+
+  protected AbstractButton hmmerBackgroundUniprot;
+
+  protected AbstractButton hmmerBackgroundAlignment;
+
+  protected JTextField hmmerSequenceCount;
+
+  protected JTextField hmmerPath;
+
+  protected JTextField cygwinPath;
+
+  /*
    * DAS Settings tab
    */
   protected JPanel dasTab = new JPanel();
@@ -274,6 +301,8 @@ public class GPreferences extends JPanel
    */
   protected JPanel wsTab = new JPanel();
 
+
+
   /**
    * Creates a new GPreferences object.
    */
@@ -325,6 +354,8 @@ public class GPreferences extends JPanel
     tabbedPane.add(initEditingTab(),
             MessageManager.getString("label.editing"));
 
+    tabbedPane.add(initHMMERTab(), MessageManager.getString("label.hmmer"));
+
     /*
      * See DasSourceBrowser for the real work of configuring this tab.
      */
@@ -339,7 +370,7 @@ public class GPreferences extends JPanel
 
     /*
      * Handler to validate a tab before leaving it - currently only for
-     * Structure.
+     * Structure
      */
     tabbedPane.addChangeListener(new ChangeListener()
     {
@@ -393,6 +424,134 @@ public class GPreferences extends JPanel
   }
 
   /**
+   * Initialises the hmmer tabbed panel
+   * 
+   * @return
+   */
+  private JPanel initHMMERTab()
+  {
+    hmmerTab = new JPanel();
+    hmmerTab.setLayout(new BoxLayout(hmmerTab, BoxLayout.Y_AXIS));
+    hmmerTab.setLayout(new MigLayout("flowy"));
+
+    /*
+     * path to hmmer binaries folder
+     */
+    JPanel installationPanel = new JPanel(new MigLayout("flowy"));
+    // new FlowLayout(FlowLayout.LEFT));
+    JvSwingUtils.createTitledBorder(installationPanel,
+            MessageManager.getString("label.installation"), true);
+    hmmerTab.add(installationPanel);
+    JLabel hmmerLocation = new JLabel(
+            MessageManager.getString("label.hmmer_location"));
+    hmmerLocation.setFont(LABEL_FONT);
+    final int pathFieldLength = 40;
+    hmmerPath = new JTextField(pathFieldLength);
+    hmmerPath.addMouseListener(new MouseAdapter()
+    {
+      @Override
+      public void mouseClicked(MouseEvent e)
+      {
+        if (e.getClickCount() == 2)
+        {
+          String chosen = openFileChooser(true);
+          if (chosen != null)
+          {
+            hmmerPath.setText(chosen);
+            validateHmmerPath();
+          }
+        }
+      }
+    });
+    installationPanel.add(hmmerLocation);
+    installationPanel.add(hmmerPath);
+
+    /*
+     * path to Cygwin binaries folder (for Windows)
+     */
+    if (Platform.isWindows())
+    {
+      JLabel cygwinLocation = new JLabel(
+              MessageManager.getString("label.cygwin_location"));
+      cygwinLocation.setFont(LABEL_FONT);
+      cygwinPath = new JTextField(pathFieldLength);
+      cygwinPath.addMouseListener(new MouseAdapter()
+      {
+        @Override
+        public void mouseClicked(MouseEvent e)
+        {
+          if (e.getClickCount() == 2)
+          {
+            String chosen = openFileChooser(true);
+            if (chosen != null)
+            {
+              cygwinPath.setText(chosen);
+              validateCygwinPath();
+            }
+          }
+        }
+      });
+      installationPanel.add(cygwinLocation);
+      installationPanel.add(cygwinPath);
+    }
+
+    /*
+     * preferences for hmmalign
+     */
+    JPanel alignOptionsPanel = new JPanel(new MigLayout());
+    // new FlowLayout(FlowLayout.LEFT));
+    JvSwingUtils.createTitledBorder(alignOptionsPanel,
+            MessageManager.getString("label.hmmalign_options"), true);
+    hmmerTab.add(alignOptionsPanel);
+    hmmrTrimTermini = new JCheckBox();
+    hmmrTrimTermini.setFont(LABEL_FONT);
+    hmmrTrimTermini.setText(MessageManager.getString("label.trim_termini"));
+    alignOptionsPanel.add(hmmrTrimTermini);
+
+    /*
+     * preferences for hmmsearch
+     */
+    JPanel searchOptions = new JPanel(new MigLayout());
+    // FlowLayout(FlowLayout.LEFT));
+    JvSwingUtils.createTitledBorder(searchOptions,
+            MessageManager.getString("label.hmmsearch_options"), true);
+    hmmerTab.add(searchOptions);
+    JLabel sequencesToKeep = new JLabel(
+            MessageManager.getString("label.no_of_sequences"));
+    sequencesToKeep.setFont(LABEL_FONT);
+    searchOptions.add(sequencesToKeep);
+    hmmerSequenceCount = new JTextField(5);
+    searchOptions.add(hmmerSequenceCount);
+
+    /*
+     * preferences for Information Content annotation
+     */
+    // JPanel dummy = new JPanel(new FlowLayout(FlowLayout.LEFT));
+    JPanel annotationOptions = new JPanel(new MigLayout("left"));
+    JvSwingUtils.createTitledBorder(annotationOptions,
+            MessageManager.getString("label.information_annotation"), true);
+    // dummy.add(annotationOptions);
+    hmmerTab.add(annotationOptions);
+    ButtonGroup backgroundOptions = new ButtonGroup();
+    hmmerBackgroundUniprot = new JRadioButton(
+            MessageManager.getString("label.freq_uniprot"));
+    hmmerBackgroundUniprot.setFont(LABEL_FONT);
+    hmmerBackgroundAlignment = new JRadioButton(
+            MessageManager.getString("label.freq_alignment"));
+    hmmerBackgroundAlignment.setFont(LABEL_FONT);
+    backgroundOptions.add(hmmerBackgroundUniprot);
+    backgroundOptions.add(hmmerBackgroundAlignment);
+    backgroundOptions.setSelected(hmmerBackgroundUniprot.getModel(), true);
+    // disable buttons for now as annotation only uses Uniprot background
+    hmmerBackgroundAlignment.setEnabled(false);
+    hmmerBackgroundUniprot.setEnabled(false);
+    annotationOptions.add(hmmerBackgroundUniprot, "wrap");
+    annotationOptions.add(hmmerBackgroundAlignment);
+
+    return hmmerTab;
+  }
+
+  /**
    * Initialises the Output tabbed panel.
    * 
    * @return
@@ -945,7 +1104,7 @@ public class GPreferences extends JPanel
     protColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
     protColourLabel.setText(
             MessageManager.getString("label.prot_alignment_colour") + " ");
-    JvSwingUtils.addtoLayout(coloursTab,
+    GPreferences.addtoLayout(coloursTab,
             MessageManager
                     .getString("label.default_colour_scheme_for_alignment"),
             protColourLabel, protColour);
@@ -957,7 +1116,7 @@ public class GPreferences extends JPanel
     nucColourLabel.setHorizontalAlignment(SwingConstants.LEFT);
     nucColourLabel.setText(
             MessageManager.getString("label.nuc_alignment_colour") + " ");
-    JvSwingUtils.addtoLayout(coloursTab,
+    GPreferences.addtoLayout(coloursTab,
             MessageManager
                     .getString("label.default_colour_scheme_for_alignment"),
             nucColourLabel, nucColour);
@@ -966,11 +1125,11 @@ public class GPreferences extends JPanel
     annotationShding.setBorder(new TitledBorder(
             MessageManager.getString("label.annotation_shading_default")));
     annotationShding.setLayout(new GridLayout(1, 2));
-    JvSwingUtils.addtoLayout(annotationShding,
+    GPreferences.addtoLayout(annotationShding,
             MessageManager.getString(
                     "label.default_minimum_colour_annotation_shading"),
             mincolourLabel, minColour);
-    JvSwingUtils.addtoLayout(annotationShding,
+    GPreferences.addtoLayout(annotationShding,
             MessageManager.getString(
                     "label.default_maximum_colour_annotation_shading"),
             maxcolourLabel, maxColour);
@@ -1222,7 +1381,7 @@ public class GPreferences extends JPanel
       {
         if (e.getClickCount() == 2)
         {
-          String chosen = openFileChooser();
+          String chosen = openFileChooser(false);
           if (chosen != null)
           {
             chimeraPath.setText(chosen);
@@ -1277,10 +1436,14 @@ public class GPreferences extends JPanel
    * 
    * @return
    */
-  protected String openFileChooser()
+  protected String openFileChooser(boolean forFolder)
   {
     String choice = null;
     JFileChooser chooser = new JFileChooser();
+    if (forFolder)
+    {
+      chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+    }
 
     // chooser.setFileView(new JalviewFileView());
     chooser.setDialogTitle(
@@ -1296,21 +1459,6 @@ public class GPreferences extends JPanel
     return choice;
   }
 
-  /**
-   * Validate the structure tab preferences; if invalid, set focus on this tab.
-   * 
-   * @param e
-   */
-  protected boolean validateStructure(FocusEvent e)
-  {
-    if (!validateStructure())
-    {
-      e.getComponent().requestFocusInWindow();
-      return false;
-    }
-    return true;
-  }
-
   protected boolean validateStructure()
   {
     return false;
@@ -1819,4 +1967,40 @@ public class GPreferences extends JPanel
     }
 
   }
+
+  protected void validateHmmerPath()
+  {
+  }
+
+  protected void validateCygwinPath()
+  {
+  }
+
+  /**
+   * A helper method to add a panel containing a label and a component to a
+   * panel
+   * 
+   * @param panel
+   * @param tooltip
+   * @param label
+   * @param valBox
+   */
+  protected static void addtoLayout(JPanel panel, String tooltip,
+          JComponent label, JComponent valBox)
+  {
+    JPanel laypanel = new JPanel(new GridLayout(1, 2));
+    JPanel labPanel = new JPanel(new BorderLayout());
+    JPanel valPanel = new JPanel();
+    labPanel.setBounds(new Rectangle(7, 7, 158, 23));
+    valPanel.setBounds(new Rectangle(172, 7, 270, 23));
+    labPanel.add(label, BorderLayout.WEST);
+    valPanel.add(valBox);
+    laypanel.add(labPanel);
+    laypanel.add(valPanel);
+    valPanel.setToolTipText(tooltip);
+    labPanel.setToolTipText(tooltip);
+    valBox.setToolTipText(tooltip);
+    panel.add(laypanel);
+    panel.validate();
+  }
 }
index 5170a6c..14ebbc0 100644 (file)
@@ -103,7 +103,7 @@ public class GRestInputParamEditDialog
     optionsPanel = new JPanel(new MigLayout("", "[fill]", "[fill]"));
     JScrollPane optionView = new JScrollPane();
     optionView.setViewportView(options);
-    JvSwingUtils.mgAddtoLayout(dpane,
+    JvSwingUtils.addtoLayout(dpane,
             MessageManager.getString("label.input_parameter_name"),
             new JLabel(MessageManager.getString("label.name")), tok,
             "grow,spanx 3,wrap");
index a4dca4b..db68757 100644 (file)
@@ -109,20 +109,20 @@ public class GRestServiceEditorPane extends JPanel
     cpanel = details;
     name = new JTextArea(1, 12);
 
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager
                     .getString("label.short_descriptive_name_for_service"),
             new JLabel(MessageManager.getString("label.name")), name,
             "wrap");
     action = new JComboBox();
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.function_service_performs"),
             new JLabel(MessageManager.getString("label.service_action")),
             action, "wrap");
     descr = new JTextArea(4, 60);
     descrVp = new JScrollPane();
     descrVp.setViewportView(descr);
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.brief_description_service"),
             new JLabel(MessageManager.getString("label.description")),
             descrVp, "wrap");
@@ -130,7 +130,7 @@ public class GRestServiceEditorPane extends JPanel
     url = new JTextArea(2, 60);
     urlVp = new JScrollPane();
     urlVp.setViewportView(url);
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.url_post_data_service"),
             new JLabel(MessageManager.getString("label.post_url")), urlVp,
             "wrap");
@@ -138,7 +138,7 @@ public class GRestServiceEditorPane extends JPanel
     urlsuff = new JTextArea();
     urlsuff.setColumns(60);
 
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.optional_suffix"),
             new JLabel(MessageManager.getString("label.url_suffix")),
             urlsuff, "wrap");
@@ -175,7 +175,7 @@ public class GRestServiceEditorPane extends JPanel
       }
     });
     gapChar = new JComboBox();
-    JvSwingUtils.mgAddtoLayout(cpanel,
+    JvSwingUtils.addtoLayout(cpanel,
             MessageManager.getString("label.preferred_gap_character"),
             new JLabel(
                     MessageManager.getString("label.gap_character") + ":"),
index adca17e..b2e569e 100644 (file)
@@ -29,12 +29,14 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.ProfilesI;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.NucleotideColourScheme;
 import jalview.schemes.ResidueProperties;
 import jalview.schemes.ZappoColourScheme;
 import jalview.util.Platform;
+import jalview.workers.InformationThread;
 
 import java.awt.BasicStroke;
 import java.awt.Color;
@@ -70,8 +72,14 @@ public class AnnotationRenderer
 
   private final boolean MAC = Platform.isAMac();
 
-  boolean av_renderHistogram = true, av_renderProfile = true,
-          av_normaliseProfile = false;
+  // todo remove these flags, read from group/viewport where needed
+  boolean av_renderHistogram = true;
+
+  boolean av_renderProfile = true;
+
+  boolean av_normaliseProfile = false;
+
+  boolean av_infoHeight = false;
 
   ResidueShaderI profcolour = null;
 
@@ -87,6 +95,8 @@ public class AnnotationRenderer
 
   private boolean av_ignoreGapsConsensus;
 
+  private boolean av_ignoreBelowBackground;
+
   /**
    * attributes set from AwtRenderPanelI
    */
@@ -341,12 +351,16 @@ public class AnnotationRenderer
     }
     columnSelection = av.getColumnSelection();
     hiddenColumns = av.getAlignment().getHiddenColumns();
-    hconsensus = av.getSequenceConsensusHash();
+    hconsensus = av.getConsensusProfiles();
     complementConsensus = av.getComplementConsensusHash();
     hStrucConsensus = av.getRnaStructureConsensusHash();
     av_ignoreGapsConsensus = av.isIgnoreGapsConsensus();
+    av_ignoreBelowBackground = av.isIgnoreBelowBackground();
+    av_infoHeight = av.isInfoLetterHeight();
   }
 
+
+
   /**
    * Returns profile data; the first element is the profile type, the second is
    * the number of distinct values, the third the total count, and the remainder
@@ -362,17 +376,25 @@ public class AnnotationRenderer
     // properties/rendering attributes as a global 'alignment group' which holds
     // all vis settings for the alignment as a whole rather than a subset
     //
-    if (aa.autoCalculated && (aa.label.startsWith("Consensus")
-            || aa.label.startsWith("cDNA Consensus")))
+    if (InformationThread.HMM_CALC_ID.equals(aa.getCalcId()))
+    {
+      HiddenMarkovModel hmm = aa.sequenceRef.getHMM();
+      return AAFrequency.extractHMMProfile(hmm, column,
+              av_ignoreBelowBackground, av_infoHeight); // TODO check if this follows standard
+                                         // pipeline
+    }
+    if (aa.autoCalculated
+            && (aa.label.startsWith("Consensus") || aa.label
+                    .startsWith("cDNA Consensus")))
     {
       boolean forComplement = aa.label.startsWith("cDNA Consensus");
-      if (aa.groupRef != null && aa.groupRef.consensusData != null
+      if (aa.groupRef != null && aa.groupRef.getConsensusData() != null
               && aa.groupRef.isShowSequenceLogo())
       {
         // TODO? group consensus for cDNA complement
         return AAFrequency.extractProfile(
-                aa.groupRef.consensusData.get(column),
-                aa.groupRef.getIgnoreGapsConsensus());
+                aa.groupRef.getConsensusData().get(column),
+                aa.groupRef.isIgnoreGapsConsensus());
       }
       // TODO extend annotation row to enable dynamic and static profile data to
       // be stored
@@ -505,6 +527,21 @@ public class AnnotationRenderer
           renderProfile = av_renderProfile;
           normaliseProfile = av_normaliseProfile;
         }
+        else if (InformationThread.HMM_CALC_ID.equals(row.getCalcId()))
+        {
+          if (row.groupRef != null)
+          {
+            renderHistogram = row.groupRef.isShowInformationHistogram();
+            renderProfile = row.groupRef.isShowHMMSequenceLogo();
+            normaliseProfile = row.groupRef.isNormaliseHMMSequenceLogo();
+          }
+          else
+          {
+            renderHistogram = av.isShowInformationHistogram();
+            renderProfile = av.isShowHMMSequenceLogo();
+            normaliseProfile = av.isNormaliseHMMSequenceLogo();
+          }
+        }
         else
         {
           renderHistogram = true;
index 4d97171..7e67598 100644 (file)
@@ -5,16 +5,16 @@
  * 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 
+ * modify it under the terms of the GNU General 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.
+ * PURPOSE.  See the GNU General License for more details.
  * 
- * You should have received a copy of the GNU General Public License
+ * You should have received a copy of the GNU General License
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
@@ -32,16 +32,15 @@ import java.util.Map;
 
 public interface ResidueShaderI
 {
+  void setConsensus(ProfilesI cons);
 
-  public abstract void setConsensus(ProfilesI cons);
+  boolean conservationApplied();
 
-  public abstract boolean conservationApplied();
+  void setConservationApplied(boolean conservationApplied);
 
-  public abstract void setConservationApplied(boolean conservationApplied);
+  void setConservation(Conservation cons);
 
-  public abstract void setConservation(Conservation cons);
-
-  public abstract void alignmentChanged(AnnotatedCollectionI alignment,
+  void alignmentChanged(AnnotatedCollectionI alignment,
           Map<SequenceI, SequenceCollectionI> hiddenReps);
 
   /**
@@ -51,19 +50,19 @@ public interface ResidueShaderI
    * @param consensusThreshold
    * @param ignoreGaps
    */
-  public abstract void setThreshold(int consensusThreshold,
+  void setThreshold(int consensusThreshold,
           boolean ignoreGaps);
 
-  public abstract void setConservationInc(int i);
+  void setConservationInc(int i);
 
-  public abstract int getConservationInc();
+  int getConservationInc();
 
   /**
    * Get the percentage threshold for this colour scheme
    * 
    * @return Returns the percentage threshold
    */
-  public abstract int getThreshold();
+  int getThreshold();
 
   /**
    * Returns the possibly context dependent colour for the given symbol at the
@@ -75,11 +74,11 @@ public interface ResidueShaderI
    * @param seq
    * @return
    */
-  public abstract Color findColour(char symbol, int position,
+  Color findColour(char symbol, int position,
           SequenceI seq);
 
-  public abstract ColourSchemeI getColourScheme();
+  ColourSchemeI getColourScheme();
 
-  public abstract void setColourScheme(ColourSchemeI cs);
+  void setColourScheme(ColourSchemeI cs);
 
 }
\ No newline at end of file
index 7c6308e..8414e28 100644 (file)
@@ -7,8 +7,8 @@
 
 package jalview.schemabinding.version2;
 
-//---------------------------------/
-//- Imported classes and packages -/
+  //---------------------------------/
+ //- Imported classes and packages -/
 //---------------------------------/
 
 import org.exolab.castor.xml.Marshaller;
@@ -19,1079 +19,1048 @@ import org.exolab.castor.xml.Unmarshaller;
  * 
  * @version $Revision$ $Date$
  */
-public class JSeq implements java.io.Serializable
-{
-
-  // --------------------------/
-  // - Class/Member Variables -/
-  // --------------------------/
-
-  /**
-   * Field _colour.
-   */
-  private int _colour;
-
-  /**
-   * keeps track of state for field: _colour
-   */
-  private boolean _has_colour;
-
-  /**
-   * Field _start.
-   */
-  private int _start;
-
-  /**
-   * keeps track of state for field: _start
-   */
-  private boolean _has_start;
-
-  /**
-   * Field _end.
-   */
-  private int _end;
-
-  /**
-   * keeps track of state for field: _end
-   */
-  private boolean _has_end;
-
-  /**
-   * Field _id.
-   */
-  private java.lang.String _id;
-
-  /**
-   * Field _hidden.
-   */
-  private boolean _hidden;
-
-  /**
-   * keeps track of state for field: _hidden
-   */
-  private boolean _has_hidden;
-
-  /**
-   * Field _viewreference.
-   */
-  private boolean _viewreference;
-
-  /**
-   * keeps track of state for field: _viewreference
-   */
-  private boolean _has_viewreference;
-
-  /**
-   * Field _featuresList.
-   */
-  private java.util.Vector _featuresList;
-
-  /**
-   * Field _pdbidsList.
-   */
-  private java.util.Vector _pdbidsList;
-
-  /**
-   * Field _hiddenSequencesList.
-   */
-  private java.util.Vector _hiddenSequencesList;
-
-  /**
-   * Reference to a viewer showing RNA structure for this sequence. Schema
-   * supports one viewer showing multiple annotations for multiple sequences,
-   * though currently only one annotation for one sequence (gapped or trimmed)
-   * is used
-   * 
-   */
-  private java.util.Vector _rnaViewerList;
-
-  // ----------------/
-  // - Constructors -/
-  // ----------------/
-
-  public JSeq()
-  {
-    super();
-    this._featuresList = new java.util.Vector();
-    this._pdbidsList = new java.util.Vector();
-    this._hiddenSequencesList = new java.util.Vector();
-    this._rnaViewerList = new java.util.Vector();
-  }
-
-  // -----------/
-  // - Methods -/
-  // -----------/
-
-  /**
-   * 
-   * 
-   * @param vFeatures
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void addFeatures(
-          final jalview.schemabinding.version2.Features vFeatures)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    this._featuresList.addElement(vFeatures);
-  }
-
-  /**
-   * 
-   * 
-   * @param index
-   * @param vFeatures
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void addFeatures(final int index,
-          final jalview.schemabinding.version2.Features vFeatures)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    this._featuresList.add(index, vFeatures);
-  }
-
-  /**
-   * 
-   * 
-   * @param vHiddenSequences
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void addHiddenSequences(final int vHiddenSequences)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    this._hiddenSequencesList.addElement(new java.lang.Integer(
-            vHiddenSequences));
-  }
-
-  /**
-   * 
-   * 
-   * @param index
-   * @param vHiddenSequences
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void addHiddenSequences(final int index, final int vHiddenSequences)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    this._hiddenSequencesList.add(index, new java.lang.Integer(
-            vHiddenSequences));
-  }
-
-  /**
-   * 
-   * 
-   * @param vPdbids
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void addPdbids(final jalview.schemabinding.version2.Pdbids vPdbids)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    this._pdbidsList.addElement(vPdbids);
-  }
-
-  /**
-   * 
-   * 
-   * @param index
-   * @param vPdbids
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void addPdbids(final int index,
-          final jalview.schemabinding.version2.Pdbids vPdbids)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    this._pdbidsList.add(index, vPdbids);
-  }
-
-  /**
-   * 
-   * 
-   * @param vRnaViewer
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void addRnaViewer(
-          final jalview.schemabinding.version2.RnaViewer vRnaViewer)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    this._rnaViewerList.addElement(vRnaViewer);
-  }
-
-  /**
-   * 
-   * 
-   * @param index
-   * @param vRnaViewer
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void addRnaViewer(final int index,
-          final jalview.schemabinding.version2.RnaViewer vRnaViewer)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    this._rnaViewerList.add(index, vRnaViewer);
-  }
-
-  /**
-     */
-  public void deleteColour()
-  {
-    this._has_colour = false;
-  }
-
-  /**
-     */
-  public void deleteEnd()
-  {
-    this._has_end = false;
-  }
-
-  /**
-     */
-  public void deleteHidden()
-  {
-    this._has_hidden = false;
-  }
-
-  /**
-     */
-  public void deleteStart()
-  {
-    this._has_start = false;
-  }
-
-  /**
-     */
-  public void deleteViewreference()
-  {
-    this._has_viewreference = false;
-  }
-
-  /**
-   * Method enumerateFeatures.
-   * 
-   * @return an Enumeration over all jalview.schemabinding.version2.Features
-   *         elements
-   */
-  public java.util.Enumeration enumerateFeatures()
-  {
-    return this._featuresList.elements();
-  }
-
-  /**
-   * Method enumerateHiddenSequences.
-   * 
-   * @return an Enumeration over all int elements
-   */
-  public java.util.Enumeration enumerateHiddenSequences()
-  {
-    return this._hiddenSequencesList.elements();
-  }
-
-  /**
-   * Method enumeratePdbids.
-   * 
-   * @return an Enumeration over all jalview.schemabinding.version2.Pdbids
-   *         elements
-   */
-  public java.util.Enumeration enumeratePdbids()
-  {
-    return this._pdbidsList.elements();
-  }
-
-  /**
-   * Method enumerateRnaViewer.
-   * 
-   * @return an Enumeration over all jalview.schemabinding.version2.RnaViewer
-   *         elements
-   */
-  public java.util.Enumeration enumerateRnaViewer()
-  {
-    return this._rnaViewerList.elements();
-  }
-
-  /**
-   * Returns the value of field 'colour'.
-   * 
-   * @return the value of field 'Colour'.
-   */
-  public int getColour()
-  {
-    return this._colour;
-  }
-
-  /**
-   * Returns the value of field 'end'.
-   * 
-   * @return the value of field 'End'.
-   */
-  public int getEnd()
-  {
-    return this._end;
-  }
-
-  /**
-   * Method getFeatures.
-   * 
-   * @param index
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   * @return the value of the jalview.schemabinding.version2.Features at the
-   *         given index
-   */
-  public jalview.schemabinding.version2.Features getFeatures(final int index)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    // check bounds for index
-    if (index < 0 || index >= this._featuresList.size())
-    {
-      throw new IndexOutOfBoundsException("getFeatures: Index value '"
-              + index + "' not in range [0.."
-              + (this._featuresList.size() - 1) + "]");
-    }
-
-    return (jalview.schemabinding.version2.Features) _featuresList
-            .get(index);
-  }
-
-  /**
-   * Method getFeatures.Returns the contents of the collection in an Array.
-   * <p>
-   * Note: Just in case the collection contents are changing in another thread,
-   * we pass a 0-length Array of the correct type into the API call. This way we
-   * <i>know</i> that the Array returned is of exactly the correct length.
-   * 
-   * @return this collection as an Array
-   */
-  public jalview.schemabinding.version2.Features[] getFeatures()
-  {
-    jalview.schemabinding.version2.Features[] array = new jalview.schemabinding.version2.Features[0];
-    return (jalview.schemabinding.version2.Features[]) this._featuresList
-            .toArray(array);
-  }
-
-  /**
-   * Method getFeaturesCount.
-   * 
-   * @return the size of this collection
-   */
-  public int getFeaturesCount()
-  {
-    return this._featuresList.size();
-  }
-
-  /**
-   * Returns the value of field 'hidden'.
-   * 
-   * @return the value of field 'Hidden'.
-   */
-  public boolean getHidden()
-  {
-    return this._hidden;
-  }
-
-  /**
-   * Method getHiddenSequences.
-   * 
-   * @param index
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   * @return the value of the int at the given index
-   */
-  public int getHiddenSequences(final int index)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    // check bounds for index
-    if (index < 0 || index >= this._hiddenSequencesList.size())
-    {
-      throw new IndexOutOfBoundsException(
-              "getHiddenSequences: Index value '" + index
-                      + "' not in range [0.."
-                      + (this._hiddenSequencesList.size() - 1) + "]");
-    }
-
-    return ((java.lang.Integer) _hiddenSequencesList.get(index)).intValue();
-  }
-
-  /**
-   * Method getHiddenSequences.Returns the contents of the collection in an
-   * Array.
-   * 
-   * @return this collection as an Array
-   */
-  public int[] getHiddenSequences()
-  {
-    int size = this._hiddenSequencesList.size();
-    int[] array = new int[size];
-    java.util.Iterator iter = _hiddenSequencesList.iterator();
-    for (int index = 0; index < size; index++)
-    {
-      array[index] = ((java.lang.Integer) iter.next()).intValue();
-    }
-    return array;
-  }
-
-  /**
-   * Method getHiddenSequencesCount.
-   * 
-   * @return the size of this collection
-   */
-  public int getHiddenSequencesCount()
-  {
-    return this._hiddenSequencesList.size();
-  }
-
-  /**
-   * Returns the value of field 'id'.
-   * 
-   * @return the value of field 'Id'.
-   */
-  public java.lang.String getId()
-  {
-    return this._id;
-  }
-
-  /**
-   * Method getPdbids.
-   * 
-   * @param index
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   * @return the value of the jalview.schemabinding.version2.Pdbids at the given
-   *         index
-   */
-  public jalview.schemabinding.version2.Pdbids getPdbids(final int index)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    // check bounds for index
-    if (index < 0 || index >= this._pdbidsList.size())
-    {
-      throw new IndexOutOfBoundsException("getPdbids: Index value '"
-              + index + "' not in range [0.."
-              + (this._pdbidsList.size() - 1) + "]");
-    }
-
-    return (jalview.schemabinding.version2.Pdbids) _pdbidsList.get(index);
-  }
-
-  /**
-   * Method getPdbids.Returns the contents of the collection in an Array.
-   * <p>
-   * Note: Just in case the collection contents are changing in another thread,
-   * we pass a 0-length Array of the correct type into the API call. This way we
-   * <i>know</i> that the Array returned is of exactly the correct length.
-   * 
-   * @return this collection as an Array
-   */
-  public jalview.schemabinding.version2.Pdbids[] getPdbids()
-  {
-    jalview.schemabinding.version2.Pdbids[] array = new jalview.schemabinding.version2.Pdbids[0];
-    return (jalview.schemabinding.version2.Pdbids[]) this._pdbidsList
-            .toArray(array);
-  }
-
-  /**
-   * Method getPdbidsCount.
-   * 
-   * @return the size of this collection
-   */
-  public int getPdbidsCount()
-  {
-    return this._pdbidsList.size();
-  }
-
-  /**
-   * Method getRnaViewer.
-   * 
-   * @param index
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   * @return the value of the jalview.schemabinding.version2.RnaViewer at the
-   *         given index
-   */
-  public jalview.schemabinding.version2.RnaViewer getRnaViewer(
-          final int index) throws java.lang.IndexOutOfBoundsException
-  {
-    // check bounds for index
-    if (index < 0 || index >= this._rnaViewerList.size())
-    {
-      throw new IndexOutOfBoundsException("getRnaViewer: Index value '"
-              + index + "' not in range [0.."
-              + (this._rnaViewerList.size() - 1) + "]");
-    }
-
-    return (jalview.schemabinding.version2.RnaViewer) _rnaViewerList
-            .get(index);
-  }
-
-  /**
-   * Method getRnaViewer.Returns the contents of the collection in an Array.
-   * <p>
-   * Note: Just in case the collection contents are changing in another thread,
-   * we pass a 0-length Array of the correct type into the API call. This way we
-   * <i>know</i> that the Array returned is of exactly the correct length.
-   * 
-   * @return this collection as an Array
-   */
-  public jalview.schemabinding.version2.RnaViewer[] getRnaViewer()
-  {
-    jalview.schemabinding.version2.RnaViewer[] array = new jalview.schemabinding.version2.RnaViewer[0];
-    return (jalview.schemabinding.version2.RnaViewer[]) this._rnaViewerList
-            .toArray(array);
-  }
-
-  /**
-   * Method getRnaViewerCount.
-   * 
-   * @return the size of this collection
-   */
-  public int getRnaViewerCount()
-  {
-    return this._rnaViewerList.size();
-  }
-
-  /**
-   * Returns the value of field 'start'.
-   * 
-   * @return the value of field 'Start'.
-   */
-  public int getStart()
-  {
-    return this._start;
-  }
-
-  /**
-   * Returns the value of field 'viewreference'.
-   * 
-   * @return the value of field 'Viewreference'.
-   */
-  public boolean getViewreference()
-  {
-    return this._viewreference;
-  }
-
-  /**
-   * Method hasColour.
-   * 
-   * @return true if at least one Colour has been added
-   */
-  public boolean hasColour()
-  {
-    return this._has_colour;
-  }
-
-  /**
-   * Method hasEnd.
-   * 
-   * @return true if at least one End has been added
-   */
-  public boolean hasEnd()
-  {
-    return this._has_end;
-  }
-
-  /**
-   * Method hasHidden.
-   * 
-   * @return true if at least one Hidden has been added
-   */
-  public boolean hasHidden()
-  {
-    return this._has_hidden;
-  }
-
-  /**
-   * Method hasStart.
-   * 
-   * @return true if at least one Start has been added
-   */
-  public boolean hasStart()
-  {
-    return this._has_start;
-  }
-
-  /**
-   * Method hasViewreference.
-   * 
-   * @return true if at least one Viewreference has been added
-   */
-  public boolean hasViewreference()
-  {
-    return this._has_viewreference;
-  }
-
-  /**
-   * Returns the value of field 'hidden'.
-   * 
-   * @return the value of field 'Hidden'.
-   */
-  public boolean isHidden()
-  {
-    return this._hidden;
-  }
-
-  /**
-   * Method isValid.
-   * 
-   * @return true if this object is valid according to the schema
-   */
-  public boolean isValid()
-  {
-    try
-    {
-      validate();
-    } catch (org.exolab.castor.xml.ValidationException vex)
-    {
-      return false;
-    }
-    return true;
-  }
-
-  /**
-   * Returns the value of field 'viewreference'.
-   * 
-   * @return the value of field 'Viewreference'.
-   */
-  public boolean isViewreference()
-  {
-    return this._viewreference;
-  }
-
-  /**
-   * 
-   * 
-   * @param out
-   * @throws org.exolab.castor.xml.MarshalException
-   *           if object is null or if any SAXException is thrown during
-   *           marshaling
-   * @throws org.exolab.castor.xml.ValidationException
-   *           if this object is an invalid instance according to the schema
-   */
-  public void marshal(final java.io.Writer out)
-          throws org.exolab.castor.xml.MarshalException,
-          org.exolab.castor.xml.ValidationException
-  {
-    Marshaller.marshal(this, out);
-  }
-
-  /**
-   * 
-   * 
-   * @param handler
-   * @throws java.io.IOException
-   *           if an IOException occurs during marshaling
-   * @throws org.exolab.castor.xml.ValidationException
-   *           if this object is an invalid instance according to the schema
-   * @throws org.exolab.castor.xml.MarshalException
-   *           if object is null or if any SAXException is thrown during
-   *           marshaling
-   */
-  public void marshal(final org.xml.sax.ContentHandler handler)
-          throws java.io.IOException,
-          org.exolab.castor.xml.MarshalException,
-          org.exolab.castor.xml.ValidationException
-  {
-    Marshaller.marshal(this, handler);
-  }
-
-  /**
-     */
-  public void removeAllFeatures()
-  {
-    this._featuresList.clear();
-  }
-
-  /**
-     */
-  public void removeAllHiddenSequences()
-  {
-    this._hiddenSequencesList.clear();
-  }
-
-  /**
-     */
-  public void removeAllPdbids()
-  {
-    this._pdbidsList.clear();
-  }
-
-  /**
-     */
-  public void removeAllRnaViewer()
-  {
-    this._rnaViewerList.clear();
-  }
-
-  /**
-   * Method removeFeatures.
-   * 
-   * @param vFeatures
-   * @return true if the object was removed from the collection.
-   */
-  public boolean removeFeatures(
-          final jalview.schemabinding.version2.Features vFeatures)
-  {
-    boolean removed = _featuresList.remove(vFeatures);
-    return removed;
-  }
-
-  /**
-   * Method removeFeaturesAt.
-   * 
-   * @param index
-   * @return the element removed from the collection
-   */
-  public jalview.schemabinding.version2.Features removeFeaturesAt(
-          final int index)
-  {
-    java.lang.Object obj = this._featuresList.remove(index);
-    return (jalview.schemabinding.version2.Features) obj;
-  }
-
-  /**
-   * Method removeHiddenSequences.
-   * 
-   * @param vHiddenSequences
-   * @return true if the object was removed from the collection.
-   */
-  public boolean removeHiddenSequences(final int vHiddenSequences)
-  {
-    boolean removed = _hiddenSequencesList.remove(new java.lang.Integer(
-            vHiddenSequences));
-    return removed;
-  }
-
-  /**
-   * Method removeHiddenSequencesAt.
-   * 
-   * @param index
-   * @return the element removed from the collection
-   */
-  public int removeHiddenSequencesAt(final int index)
-  {
-    java.lang.Object obj = this._hiddenSequencesList.remove(index);
-    return ((java.lang.Integer) obj).intValue();
-  }
-
-  /**
-   * Method removePdbids.
-   * 
-   * @param vPdbids
-   * @return true if the object was removed from the collection.
-   */
-  public boolean removePdbids(
-          final jalview.schemabinding.version2.Pdbids vPdbids)
-  {
-    boolean removed = _pdbidsList.remove(vPdbids);
-    return removed;
-  }
-
-  /**
-   * Method removePdbidsAt.
-   * 
-   * @param index
-   * @return the element removed from the collection
-   */
-  public jalview.schemabinding.version2.Pdbids removePdbidsAt(
-          final int index)
-  {
-    java.lang.Object obj = this._pdbidsList.remove(index);
-    return (jalview.schemabinding.version2.Pdbids) obj;
-  }
-
-  /**
-   * Method removeRnaViewer.
-   * 
-   * @param vRnaViewer
-   * @return true if the object was removed from the collection.
-   */
-  public boolean removeRnaViewer(
-          final jalview.schemabinding.version2.RnaViewer vRnaViewer)
-  {
-    boolean removed = _rnaViewerList.remove(vRnaViewer);
-    return removed;
-  }
-
-  /**
-   * Method removeRnaViewerAt.
-   * 
-   * @param index
-   * @return the element removed from the collection
-   */
-  public jalview.schemabinding.version2.RnaViewer removeRnaViewerAt(
-          final int index)
-  {
-    java.lang.Object obj = this._rnaViewerList.remove(index);
-    return (jalview.schemabinding.version2.RnaViewer) obj;
-  }
-
-  /**
-   * Sets the value of field 'colour'.
-   * 
-   * @param colour
-   *          the value of field 'colour'.
-   */
-  public void setColour(final int colour)
-  {
-    this._colour = colour;
-    this._has_colour = true;
-  }
-
-  /**
-   * Sets the value of field 'end'.
-   * 
-   * @param end
-   *          the value of field 'end'.
-   */
-  public void setEnd(final int end)
-  {
-    this._end = end;
-    this._has_end = true;
-  }
-
-  /**
-   * 
-   * 
-   * @param index
-   * @param vFeatures
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void setFeatures(final int index,
-          final jalview.schemabinding.version2.Features vFeatures)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    // check bounds for index
-    if (index < 0 || index >= this._featuresList.size())
-    {
-      throw new IndexOutOfBoundsException("setFeatures: Index value '"
-              + index + "' not in range [0.."
-              + (this._featuresList.size() - 1) + "]");
-    }
-
-    this._featuresList.set(index, vFeatures);
-  }
-
-  /**
-   * 
-   * 
-   * @param vFeaturesArray
-   */
-  public void setFeatures(
-          final jalview.schemabinding.version2.Features[] vFeaturesArray)
-  {
-    // -- copy array
-    _featuresList.clear();
-
-    for (int i = 0; i < vFeaturesArray.length; i++)
-    {
-      this._featuresList.add(vFeaturesArray[i]);
-    }
-  }
-
-  /**
-   * Sets the value of field 'hidden'.
-   * 
-   * @param hidden
-   *          the value of field 'hidden'.
-   */
-  public void setHidden(final boolean hidden)
-  {
-    this._hidden = hidden;
-    this._has_hidden = true;
-  }
-
-  /**
-   * 
-   * 
-   * @param index
-   * @param vHiddenSequences
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void setHiddenSequences(final int index, final int vHiddenSequences)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    // check bounds for index
-    if (index < 0 || index >= this._hiddenSequencesList.size())
-    {
-      throw new IndexOutOfBoundsException(
-              "setHiddenSequences: Index value '" + index
-                      + "' not in range [0.."
-                      + (this._hiddenSequencesList.size() - 1) + "]");
-    }
-
-    this._hiddenSequencesList.set(index, new java.lang.Integer(
-            vHiddenSequences));
-  }
-
-  /**
-   * 
-   * 
-   * @param vHiddenSequencesArray
-   */
-  public void setHiddenSequences(final int[] vHiddenSequencesArray)
-  {
-    // -- copy array
-    _hiddenSequencesList.clear();
-
-    for (int i = 0; i < vHiddenSequencesArray.length; i++)
-    {
-      this._hiddenSequencesList.add(new java.lang.Integer(
-              vHiddenSequencesArray[i]));
-    }
-  }
-
-  /**
-   * Sets the value of field 'id'.
-   * 
-   * @param id
-   *          the value of field 'id'.
-   */
-  public void setId(final java.lang.String id)
-  {
-    this._id = id;
-  }
-
-  /**
-   * 
-   * 
-   * @param index
-   * @param vPdbids
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void setPdbids(final int index,
-          final jalview.schemabinding.version2.Pdbids vPdbids)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    // check bounds for index
-    if (index < 0 || index >= this._pdbidsList.size())
-    {
-      throw new IndexOutOfBoundsException("setPdbids: Index value '"
-              + index + "' not in range [0.."
-              + (this._pdbidsList.size() - 1) + "]");
-    }
-
-    this._pdbidsList.set(index, vPdbids);
-  }
-
-  /**
-   * 
-   * 
-   * @param vPdbidsArray
-   */
-  public void setPdbids(
-          final jalview.schemabinding.version2.Pdbids[] vPdbidsArray)
-  {
-    // -- copy array
-    _pdbidsList.clear();
-
-    for (int i = 0; i < vPdbidsArray.length; i++)
-    {
-      this._pdbidsList.add(vPdbidsArray[i]);
-    }
-  }
-
-  /**
-   * 
-   * 
-   * @param index
-   * @param vRnaViewer
-   * @throws java.lang.IndexOutOfBoundsException
-   *           if the index given is outside the bounds of the collection
-   */
-  public void setRnaViewer(final int index,
-          final jalview.schemabinding.version2.RnaViewer vRnaViewer)
-          throws java.lang.IndexOutOfBoundsException
-  {
-    // check bounds for index
-    if (index < 0 || index >= this._rnaViewerList.size())
-    {
-      throw new IndexOutOfBoundsException("setRnaViewer: Index value '"
-              + index + "' not in range [0.."
-              + (this._rnaViewerList.size() - 1) + "]");
-    }
-
-    this._rnaViewerList.set(index, vRnaViewer);
-  }
-
-  /**
-   * 
-   * 
-   * @param vRnaViewerArray
-   */
-  public void setRnaViewer(
-          final jalview.schemabinding.version2.RnaViewer[] vRnaViewerArray)
-  {
-    // -- copy array
-    _rnaViewerList.clear();
-
-    for (int i = 0; i < vRnaViewerArray.length; i++)
-    {
-      this._rnaViewerList.add(vRnaViewerArray[i]);
-    }
-  }
-
-  /**
-   * Sets the value of field 'start'.
-   * 
-   * @param start
-   *          the value of field 'start'.
-   */
-  public void setStart(final int start)
-  {
-    this._start = start;
-    this._has_start = true;
-  }
-
-  /**
-   * Sets the value of field 'viewreference'.
-   * 
-   * @param viewreference
-   *          the value of field 'viewreference'.
-   */
-  public void setViewreference(final boolean viewreference)
-  {
-    this._viewreference = viewreference;
-    this._has_viewreference = true;
-  }
-
-  /**
-   * Method unmarshal.
-   * 
-   * @param reader
-   * @throws org.exolab.castor.xml.MarshalException
-   *           if object is null or if any SAXException is thrown during
-   *           marshaling
-   * @throws org.exolab.castor.xml.ValidationException
-   *           if this object is an invalid instance according to the schema
-   * @return the unmarshaled jalview.schemabinding.version2.JSeq
-   */
-  public static jalview.schemabinding.version2.JSeq unmarshal(
-          final java.io.Reader reader)
-          throws org.exolab.castor.xml.MarshalException,
-          org.exolab.castor.xml.ValidationException
-  {
-    return (jalview.schemabinding.version2.JSeq) Unmarshaller.unmarshal(
-            jalview.schemabinding.version2.JSeq.class, reader);
-  }
-
-  /**
-   * 
-   * 
-   * @throws org.exolab.castor.xml.ValidationException
-   *           if this object is an invalid instance according to the schema
-   */
-  public void validate() throws org.exolab.castor.xml.ValidationException
-  {
-    org.exolab.castor.xml.Validator validator = new org.exolab.castor.xml.Validator();
-    validator.validate(this);
-  }
+public class JSeq implements java.io.Serializable {
+
+
+      //--------------------------/
+     //- Class/Member Variables -/
+    //--------------------------/
+
+    /**
+     * Field _colour.
+     */
+    private int _colour;
+
+    /**
+     * keeps track of state for field: _colour
+     */
+    private boolean _has_colour;
+
+    /**
+     * Field _start.
+     */
+    private int _start;
+
+    /**
+     * keeps track of state for field: _start
+     */
+    private boolean _has_start;
+
+    /**
+     * Field _end.
+     */
+    private int _end;
+
+    /**
+     * keeps track of state for field: _end
+     */
+    private boolean _has_end;
+
+    /**
+     * Field _id.
+     */
+    private java.lang.String _id;
+
+    /**
+     * Field _hidden.
+     */
+    private boolean _hidden;
+
+    /**
+     * keeps track of state for field: _hidden
+     */
+    private boolean _has_hidden;
+
+    /**
+     * Field _viewreference.
+     */
+    private boolean _viewreference;
+
+    /**
+     * keeps track of state for field: _viewreference
+     */
+    private boolean _has_viewreference;
+
+    /**
+     * Field _featuresList.
+     */
+    private java.util.Vector _featuresList;
+
+    /**
+     * Field _pdbidsList.
+     */
+    private java.util.Vector _pdbidsList;
+
+    /**
+     * Field _hiddenSequencesList.
+     */
+    private java.util.Vector _hiddenSequencesList;
+
+    /**
+     * Reference to a viewer showing RNA structure
+     *  for this sequence. Schema supports one viewer showing
+     * multiple
+     *  annotations for multiple sequences, though currently only
+     * one
+     *  annotation for one sequence (gapped or trimmed) is used
+     *  
+     */
+    private java.util.Vector _rnaViewerList;
+
+    /**
+     * name of the project jar entry that holds the HMM file with
+     * the profile for the sequence
+     */
+    private java.lang.String _hmmerProfile;
+
+
+      //----------------/
+     //- Constructors -/
+    //----------------/
+
+    public JSeq() {
+        super();
+        this._featuresList = new java.util.Vector();
+        this._pdbidsList = new java.util.Vector();
+        this._hiddenSequencesList = new java.util.Vector();
+        this._rnaViewerList = new java.util.Vector();
+    }
+
+
+      //-----------/
+     //- Methods -/
+    //-----------/
+
+    /**
+     * 
+     * 
+     * @param vFeatures
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addFeatures(
+            final jalview.schemabinding.version2.Features vFeatures)
+    throws java.lang.IndexOutOfBoundsException {
+        this._featuresList.addElement(vFeatures);
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vFeatures
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addFeatures(
+            final int index,
+            final jalview.schemabinding.version2.Features vFeatures)
+    throws java.lang.IndexOutOfBoundsException {
+        this._featuresList.add(index, vFeatures);
+    }
+
+    /**
+     * 
+     * 
+     * @param vHiddenSequences
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addHiddenSequences(
+            final int vHiddenSequences)
+    throws java.lang.IndexOutOfBoundsException {
+        this._hiddenSequencesList.addElement(new java.lang.Integer(vHiddenSequences));
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vHiddenSequences
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addHiddenSequences(
+            final int index,
+            final int vHiddenSequences)
+    throws java.lang.IndexOutOfBoundsException {
+        this._hiddenSequencesList.add(index, new java.lang.Integer(vHiddenSequences));
+    }
+
+    /**
+     * 
+     * 
+     * @param vPdbids
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addPdbids(
+            final jalview.schemabinding.version2.Pdbids vPdbids)
+    throws java.lang.IndexOutOfBoundsException {
+        this._pdbidsList.addElement(vPdbids);
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vPdbids
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addPdbids(
+            final int index,
+            final jalview.schemabinding.version2.Pdbids vPdbids)
+    throws java.lang.IndexOutOfBoundsException {
+        this._pdbidsList.add(index, vPdbids);
+    }
+
+    /**
+     * 
+     * 
+     * @param vRnaViewer
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addRnaViewer(
+            final jalview.schemabinding.version2.RnaViewer vRnaViewer)
+    throws java.lang.IndexOutOfBoundsException {
+        this._rnaViewerList.addElement(vRnaViewer);
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vRnaViewer
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void addRnaViewer(
+            final int index,
+            final jalview.schemabinding.version2.RnaViewer vRnaViewer)
+    throws java.lang.IndexOutOfBoundsException {
+        this._rnaViewerList.add(index, vRnaViewer);
+    }
+
+    /**
+     */
+    public void deleteColour(
+    ) {
+        this._has_colour= false;
+    }
+
+    /**
+     */
+    public void deleteEnd(
+    ) {
+        this._has_end= false;
+    }
+
+    /**
+     */
+    public void deleteHidden(
+    ) {
+        this._has_hidden= false;
+    }
+
+    /**
+     */
+    public void deleteStart(
+    ) {
+        this._has_start= false;
+    }
+
+    /**
+     */
+    public void deleteViewreference(
+    ) {
+        this._has_viewreference= false;
+    }
+
+    /**
+     * Method enumerateFeatures.
+     * 
+     * @return an Enumeration over all
+     * jalview.schemabinding.version2.Features elements
+     */
+    public java.util.Enumeration enumerateFeatures(
+    ) {
+        return this._featuresList.elements();
+    }
+
+    /**
+     * Method enumerateHiddenSequences.
+     * 
+     * @return an Enumeration over all int elements
+     */
+    public java.util.Enumeration enumerateHiddenSequences(
+    ) {
+        return this._hiddenSequencesList.elements();
+    }
+
+    /**
+     * Method enumeratePdbids.
+     * 
+     * @return an Enumeration over all
+     * jalview.schemabinding.version2.Pdbids elements
+     */
+    public java.util.Enumeration enumeratePdbids(
+    ) {
+        return this._pdbidsList.elements();
+    }
+
+    /**
+     * Method enumerateRnaViewer.
+     * 
+     * @return an Enumeration over all
+     * jalview.schemabinding.version2.RnaViewer elements
+     */
+    public java.util.Enumeration enumerateRnaViewer(
+    ) {
+        return this._rnaViewerList.elements();
+    }
+
+    /**
+     * Returns the value of field 'colour'.
+     * 
+     * @return the value of field 'Colour'.
+     */
+    public int getColour(
+    ) {
+        return this._colour;
+    }
+
+    /**
+     * Returns the value of field 'end'.
+     * 
+     * @return the value of field 'End'.
+     */
+    public int getEnd(
+    ) {
+        return this._end;
+    }
+
+    /**
+     * Method getFeatures.
+     * 
+     * @param index
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     * @return the value of the
+     * jalview.schemabinding.version2.Features at the given index
+     */
+    public jalview.schemabinding.version2.Features getFeatures(
+            final int index)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._featuresList.size()) {
+            throw new IndexOutOfBoundsException("getFeatures: Index value '" + index + "' not in range [0.." + (this._featuresList.size() - 1) + "]");
+        }
+        
+        return (jalview.schemabinding.version2.Features) _featuresList.get(index);
+    }
+
+    /**
+     * Method getFeatures.Returns the contents of the collection in
+     * an Array.  <p>Note:  Just in case the collection contents
+     * are changing in another thread, we pass a 0-length Array of
+     * the correct type into the API call.  This way we <i>know</i>
+     * that the Array returned is of exactly the correct length.
+     * 
+     * @return this collection as an Array
+     */
+    public jalview.schemabinding.version2.Features[] getFeatures(
+    ) {
+        jalview.schemabinding.version2.Features[] array = new jalview.schemabinding.version2.Features[0];
+        return (jalview.schemabinding.version2.Features[]) this._featuresList.toArray(array);
+    }
+
+    /**
+     * Method getFeaturesCount.
+     * 
+     * @return the size of this collection
+     */
+    public int getFeaturesCount(
+    ) {
+        return this._featuresList.size();
+    }
+
+    /**
+     * Returns the value of field 'hidden'.
+     * 
+     * @return the value of field 'Hidden'.
+     */
+    public boolean getHidden(
+    ) {
+        return this._hidden;
+    }
+
+    /**
+     * Method getHiddenSequences.
+     * 
+     * @param index
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     * @return the value of the int at the given index
+     */
+    public int getHiddenSequences(
+            final int index)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._hiddenSequencesList.size()) {
+            throw new IndexOutOfBoundsException("getHiddenSequences: Index value '" + index + "' not in range [0.." + (this._hiddenSequencesList.size() - 1) + "]");
+        }
+        
+        return ((java.lang.Integer) _hiddenSequencesList.get(index)).intValue();
+    }
+
+    /**
+     * Method getHiddenSequences.Returns the contents of the
+     * collection in an Array.  
+     * 
+     * @return this collection as an Array
+     */
+    public int[] getHiddenSequences(
+    ) {
+        int size = this._hiddenSequencesList.size();
+        int[] array = new int[size];
+        java.util.Iterator iter = _hiddenSequencesList.iterator();
+        for (int index = 0; index < size; index++) {
+            array[index] = ((java.lang.Integer) iter.next()).intValue();
+        }
+        return array;
+    }
+
+    /**
+     * Method getHiddenSequencesCount.
+     * 
+     * @return the size of this collection
+     */
+    public int getHiddenSequencesCount(
+    ) {
+        return this._hiddenSequencesList.size();
+    }
+
+    /**
+     * Returns the value of field 'hmmerProfile'. The field
+     * 'hmmerProfile' has the following description: name of the
+     * project jar entry that holds the HMM file with the profile
+     * for the sequence
+     * 
+     * @return the value of field 'HmmerProfile'.
+     */
+    public java.lang.String getHmmerProfile(
+    ) {
+        return this._hmmerProfile;
+    }
+
+    /**
+     * Returns the value of field 'id'.
+     * 
+     * @return the value of field 'Id'.
+     */
+    public java.lang.String getId(
+    ) {
+        return this._id;
+    }
+
+    /**
+     * Method getPdbids.
+     * 
+     * @param index
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     * @return the value of the
+     * jalview.schemabinding.version2.Pdbids at the given index
+     */
+    public jalview.schemabinding.version2.Pdbids getPdbids(
+            final int index)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._pdbidsList.size()) {
+            throw new IndexOutOfBoundsException("getPdbids: Index value '" + index + "' not in range [0.." + (this._pdbidsList.size() - 1) + "]");
+        }
+        
+        return (jalview.schemabinding.version2.Pdbids) _pdbidsList.get(index);
+    }
+
+    /**
+     * Method getPdbids.Returns the contents of the collection in
+     * an Array.  <p>Note:  Just in case the collection contents
+     * are changing in another thread, we pass a 0-length Array of
+     * the correct type into the API call.  This way we <i>know</i>
+     * that the Array returned is of exactly the correct length.
+     * 
+     * @return this collection as an Array
+     */
+    public jalview.schemabinding.version2.Pdbids[] getPdbids(
+    ) {
+        jalview.schemabinding.version2.Pdbids[] array = new jalview.schemabinding.version2.Pdbids[0];
+        return (jalview.schemabinding.version2.Pdbids[]) this._pdbidsList.toArray(array);
+    }
+
+    /**
+     * Method getPdbidsCount.
+     * 
+     * @return the size of this collection
+     */
+    public int getPdbidsCount(
+    ) {
+        return this._pdbidsList.size();
+    }
+
+    /**
+     * Method getRnaViewer.
+     * 
+     * @param index
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     * @return the value of the
+     * jalview.schemabinding.version2.RnaViewer at the given index
+     */
+    public jalview.schemabinding.version2.RnaViewer getRnaViewer(
+            final int index)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._rnaViewerList.size()) {
+            throw new IndexOutOfBoundsException("getRnaViewer: Index value '" + index + "' not in range [0.." + (this._rnaViewerList.size() - 1) + "]");
+        }
+        
+        return (jalview.schemabinding.version2.RnaViewer) _rnaViewerList.get(index);
+    }
+
+    /**
+     * Method getRnaViewer.Returns the contents of the collection
+     * in an Array.  <p>Note:  Just in case the collection contents
+     * are changing in another thread, we pass a 0-length Array of
+     * the correct type into the API call.  This way we <i>know</i>
+     * that the Array returned is of exactly the correct length.
+     * 
+     * @return this collection as an Array
+     */
+    public jalview.schemabinding.version2.RnaViewer[] getRnaViewer(
+    ) {
+        jalview.schemabinding.version2.RnaViewer[] array = new jalview.schemabinding.version2.RnaViewer[0];
+        return (jalview.schemabinding.version2.RnaViewer[]) this._rnaViewerList.toArray(array);
+    }
+
+    /**
+     * Method getRnaViewerCount.
+     * 
+     * @return the size of this collection
+     */
+    public int getRnaViewerCount(
+    ) {
+        return this._rnaViewerList.size();
+    }
+
+    /**
+     * Returns the value of field 'start'.
+     * 
+     * @return the value of field 'Start'.
+     */
+    public int getStart(
+    ) {
+        return this._start;
+    }
+
+    /**
+     * Returns the value of field 'viewreference'.
+     * 
+     * @return the value of field 'Viewreference'.
+     */
+    public boolean getViewreference(
+    ) {
+        return this._viewreference;
+    }
+
+    /**
+     * Method hasColour.
+     * 
+     * @return true if at least one Colour has been added
+     */
+    public boolean hasColour(
+    ) {
+        return this._has_colour;
+    }
+
+    /**
+     * Method hasEnd.
+     * 
+     * @return true if at least one End has been added
+     */
+    public boolean hasEnd(
+    ) {
+        return this._has_end;
+    }
+
+    /**
+     * Method hasHidden.
+     * 
+     * @return true if at least one Hidden has been added
+     */
+    public boolean hasHidden(
+    ) {
+        return this._has_hidden;
+    }
+
+    /**
+     * Method hasStart.
+     * 
+     * @return true if at least one Start has been added
+     */
+    public boolean hasStart(
+    ) {
+        return this._has_start;
+    }
+
+    /**
+     * Method hasViewreference.
+     * 
+     * @return true if at least one Viewreference has been added
+     */
+    public boolean hasViewreference(
+    ) {
+        return this._has_viewreference;
+    }
+
+    /**
+     * Returns the value of field 'hidden'.
+     * 
+     * @return the value of field 'Hidden'.
+     */
+    public boolean isHidden(
+    ) {
+        return this._hidden;
+    }
+
+    /**
+     * Method isValid.
+     * 
+     * @return true if this object is valid according to the schema
+     */
+    public boolean isValid(
+    ) {
+        try {
+            validate();
+        } catch (org.exolab.castor.xml.ValidationException vex) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns the value of field 'viewreference'.
+     * 
+     * @return the value of field 'Viewreference'.
+     */
+    public boolean isViewreference(
+    ) {
+        return this._viewreference;
+    }
+
+    /**
+     * 
+     * 
+     * @param out
+     * @throws org.exolab.castor.xml.MarshalException if object is
+     * null or if any SAXException is thrown during marshaling
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     */
+    public void marshal(
+            final java.io.Writer out)
+    throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+        Marshaller.marshal(this, out);
+    }
+
+    /**
+     * 
+     * 
+     * @param handler
+     * @throws java.io.IOException if an IOException occurs during
+     * marshaling
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     * @throws org.exolab.castor.xml.MarshalException if object is
+     * null or if any SAXException is thrown during marshaling
+     */
+    public void marshal(
+            final org.xml.sax.ContentHandler handler)
+    throws java.io.IOException, org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+        Marshaller.marshal(this, handler);
+    }
+
+    /**
+     */
+    public void removeAllFeatures(
+    ) {
+        this._featuresList.clear();
+    }
+
+    /**
+     */
+    public void removeAllHiddenSequences(
+    ) {
+        this._hiddenSequencesList.clear();
+    }
+
+    /**
+     */
+    public void removeAllPdbids(
+    ) {
+        this._pdbidsList.clear();
+    }
+
+    /**
+     */
+    public void removeAllRnaViewer(
+    ) {
+        this._rnaViewerList.clear();
+    }
+
+    /**
+     * Method removeFeatures.
+     * 
+     * @param vFeatures
+     * @return true if the object was removed from the collection.
+     */
+    public boolean removeFeatures(
+            final jalview.schemabinding.version2.Features vFeatures) {
+        boolean removed = _featuresList.remove(vFeatures);
+        return removed;
+    }
+
+    /**
+     * Method removeFeaturesAt.
+     * 
+     * @param index
+     * @return the element removed from the collection
+     */
+    public jalview.schemabinding.version2.Features removeFeaturesAt(
+            final int index) {
+        java.lang.Object obj = this._featuresList.remove(index);
+        return (jalview.schemabinding.version2.Features) obj;
+    }
+
+    /**
+     * Method removeHiddenSequences.
+     * 
+     * @param vHiddenSequences
+     * @return true if the object was removed from the collection.
+     */
+    public boolean removeHiddenSequences(
+            final int vHiddenSequences) {
+        boolean removed = _hiddenSequencesList.remove(new java.lang.Integer(vHiddenSequences));
+        return removed;
+    }
+
+    /**
+     * Method removeHiddenSequencesAt.
+     * 
+     * @param index
+     * @return the element removed from the collection
+     */
+    public int removeHiddenSequencesAt(
+            final int index) {
+        java.lang.Object obj = this._hiddenSequencesList.remove(index);
+        return ((java.lang.Integer) obj).intValue();
+    }
+
+    /**
+     * Method removePdbids.
+     * 
+     * @param vPdbids
+     * @return true if the object was removed from the collection.
+     */
+    public boolean removePdbids(
+            final jalview.schemabinding.version2.Pdbids vPdbids) {
+        boolean removed = _pdbidsList.remove(vPdbids);
+        return removed;
+    }
+
+    /**
+     * Method removePdbidsAt.
+     * 
+     * @param index
+     * @return the element removed from the collection
+     */
+    public jalview.schemabinding.version2.Pdbids removePdbidsAt(
+            final int index) {
+        java.lang.Object obj = this._pdbidsList.remove(index);
+        return (jalview.schemabinding.version2.Pdbids) obj;
+    }
+
+    /**
+     * Method removeRnaViewer.
+     * 
+     * @param vRnaViewer
+     * @return true if the object was removed from the collection.
+     */
+    public boolean removeRnaViewer(
+            final jalview.schemabinding.version2.RnaViewer vRnaViewer) {
+        boolean removed = _rnaViewerList.remove(vRnaViewer);
+        return removed;
+    }
+
+    /**
+     * Method removeRnaViewerAt.
+     * 
+     * @param index
+     * @return the element removed from the collection
+     */
+    public jalview.schemabinding.version2.RnaViewer removeRnaViewerAt(
+            final int index) {
+        java.lang.Object obj = this._rnaViewerList.remove(index);
+        return (jalview.schemabinding.version2.RnaViewer) obj;
+    }
+
+    /**
+     * Sets the value of field 'colour'.
+     * 
+     * @param colour the value of field 'colour'.
+     */
+    public void setColour(
+            final int colour) {
+        this._colour = colour;
+        this._has_colour = true;
+    }
+
+    /**
+     * Sets the value of field 'end'.
+     * 
+     * @param end the value of field 'end'.
+     */
+    public void setEnd(
+            final int end) {
+        this._end = end;
+        this._has_end = true;
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vFeatures
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void setFeatures(
+            final int index,
+            final jalview.schemabinding.version2.Features vFeatures)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._featuresList.size()) {
+            throw new IndexOutOfBoundsException("setFeatures: Index value '" + index + "' not in range [0.." + (this._featuresList.size() - 1) + "]");
+        }
+        
+        this._featuresList.set(index, vFeatures);
+    }
+
+    /**
+     * 
+     * 
+     * @param vFeaturesArray
+     */
+    public void setFeatures(
+            final jalview.schemabinding.version2.Features[] vFeaturesArray) {
+        //-- copy array
+        _featuresList.clear();
+        
+        for (int i = 0; i < vFeaturesArray.length; i++) {
+                this._featuresList.add(vFeaturesArray[i]);
+        }
+    }
+
+    /**
+     * Sets the value of field 'hidden'.
+     * 
+     * @param hidden the value of field 'hidden'.
+     */
+    public void setHidden(
+            final boolean hidden) {
+        this._hidden = hidden;
+        this._has_hidden = true;
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vHiddenSequences
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void setHiddenSequences(
+            final int index,
+            final int vHiddenSequences)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._hiddenSequencesList.size()) {
+            throw new IndexOutOfBoundsException("setHiddenSequences: Index value '" + index + "' not in range [0.." + (this._hiddenSequencesList.size() - 1) + "]");
+        }
+        
+        this._hiddenSequencesList.set(index, new java.lang.Integer(vHiddenSequences));
+    }
+
+    /**
+     * 
+     * 
+     * @param vHiddenSequencesArray
+     */
+    public void setHiddenSequences(
+            final int[] vHiddenSequencesArray) {
+        //-- copy array
+        _hiddenSequencesList.clear();
+        
+        for (int i = 0; i < vHiddenSequencesArray.length; i++) {
+                this._hiddenSequencesList.add(new java.lang.Integer(vHiddenSequencesArray[i]));
+        }
+    }
+
+    /**
+     * Sets the value of field 'hmmerProfile'. The field
+     * 'hmmerProfile' has the following description: name of the
+     * project jar entry that holds the HMM file with the profile
+     * for the sequence
+     * 
+     * @param hmmerProfile the value of field 'hmmerProfile'.
+     */
+    public void setHmmerProfile(
+            final java.lang.String hmmerProfile) {
+        this._hmmerProfile = hmmerProfile;
+    }
+
+    /**
+     * Sets the value of field 'id'.
+     * 
+     * @param id the value of field 'id'.
+     */
+    public void setId(
+            final java.lang.String id) {
+        this._id = id;
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vPdbids
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void setPdbids(
+            final int index,
+            final jalview.schemabinding.version2.Pdbids vPdbids)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._pdbidsList.size()) {
+            throw new IndexOutOfBoundsException("setPdbids: Index value '" + index + "' not in range [0.." + (this._pdbidsList.size() - 1) + "]");
+        }
+        
+        this._pdbidsList.set(index, vPdbids);
+    }
+
+    /**
+     * 
+     * 
+     * @param vPdbidsArray
+     */
+    public void setPdbids(
+            final jalview.schemabinding.version2.Pdbids[] vPdbidsArray) {
+        //-- copy array
+        _pdbidsList.clear();
+        
+        for (int i = 0; i < vPdbidsArray.length; i++) {
+                this._pdbidsList.add(vPdbidsArray[i]);
+        }
+    }
+
+    /**
+     * 
+     * 
+     * @param index
+     * @param vRnaViewer
+     * @throws java.lang.IndexOutOfBoundsException if the index
+     * given is outside the bounds of the collection
+     */
+    public void setRnaViewer(
+            final int index,
+            final jalview.schemabinding.version2.RnaViewer vRnaViewer)
+    throws java.lang.IndexOutOfBoundsException {
+        // check bounds for index
+        if (index < 0 || index >= this._rnaViewerList.size()) {
+            throw new IndexOutOfBoundsException("setRnaViewer: Index value '" + index + "' not in range [0.." + (this._rnaViewerList.size() - 1) + "]");
+        }
+        
+        this._rnaViewerList.set(index, vRnaViewer);
+    }
+
+    /**
+     * 
+     * 
+     * @param vRnaViewerArray
+     */
+    public void setRnaViewer(
+            final jalview.schemabinding.version2.RnaViewer[] vRnaViewerArray) {
+        //-- copy array
+        _rnaViewerList.clear();
+        
+        for (int i = 0; i < vRnaViewerArray.length; i++) {
+                this._rnaViewerList.add(vRnaViewerArray[i]);
+        }
+    }
+
+    /**
+     * Sets the value of field 'start'.
+     * 
+     * @param start the value of field 'start'.
+     */
+    public void setStart(
+            final int start) {
+        this._start = start;
+        this._has_start = true;
+    }
+
+    /**
+     * Sets the value of field 'viewreference'.
+     * 
+     * @param viewreference the value of field 'viewreference'.
+     */
+    public void setViewreference(
+            final boolean viewreference) {
+        this._viewreference = viewreference;
+        this._has_viewreference = true;
+    }
+
+    /**
+     * Method unmarshal.
+     * 
+     * @param reader
+     * @throws org.exolab.castor.xml.MarshalException if object is
+     * null or if any SAXException is thrown during marshaling
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     * @return the unmarshaled jalview.schemabinding.version2.JSeq
+     */
+    public static jalview.schemabinding.version2.JSeq unmarshal(
+            final java.io.Reader reader)
+    throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+        return (jalview.schemabinding.version2.JSeq) Unmarshaller.unmarshal(jalview.schemabinding.version2.JSeq.class, reader);
+    }
+
+    /**
+     * 
+     * 
+     * @throws org.exolab.castor.xml.ValidationException if this
+     * object is an invalid instance according to the schema
+     */
+    public void validate(
+    )
+    throws org.exolab.castor.xml.ValidationException {
+        org.exolab.castor.xml.Validator validator = new org.exolab.castor.xml.Validator();
+        validator.validate(this);
+    }
 
 }
index 28f23b2..b6becc0 100644 (file)
@@ -7,8 +7,8 @@
 
 package jalview.schemabinding.version2.descriptors;
 
-//---------------------------------/
-//- Imported classes and packages -/
+  //---------------------------------/
+ //- Imported classes and packages -/
 //---------------------------------/
 
 import jalview.schemabinding.version2.JSeq;
@@ -18,697 +18,607 @@ import jalview.schemabinding.version2.JSeq;
  * 
  * @version $Revision$ $Date$
  */
-public class JSeqDescriptor extends
-        org.exolab.castor.xml.util.XMLClassDescriptorImpl
-{
-
-  // --------------------------/
-  // - Class/Member Variables -/
-  // --------------------------/
-
-  /**
-   * Field _elementDefinition.
-   */
-  private boolean _elementDefinition;
-
-  /**
-   * Field _nsPrefix.
-   */
-  private java.lang.String _nsPrefix;
-
-  /**
-   * Field _nsURI.
-   */
-  private java.lang.String _nsURI;
-
-  /**
-   * Field _xmlName.
-   */
-  private java.lang.String _xmlName;
-
-  // ----------------/
-  // - Constructors -/
-  // ----------------/
-
-  public JSeqDescriptor()
-  {
-    super();
-    _nsURI = "www.jalview.org";
-    _xmlName = "JSeq";
-    _elementDefinition = true;
-
-    // -- set grouping compositor
-    setCompositorAsSequence();
-    org.exolab.castor.xml.util.XMLFieldDescriptorImpl desc = null;
-    org.exolab.castor.mapping.FieldHandler handler = null;
-    org.exolab.castor.xml.FieldValidator fieldValidator = null;
-    // -- initialize attribute descriptors
-
-    // -- _colour
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            java.lang.Integer.TYPE, "_colour", "colour",
-            org.exolab.castor.xml.NodeType.Attribute);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        if (!target.hasColour())
-        {
-          return null;
+public class JSeqDescriptor extends org.exolab.castor.xml.util.XMLClassDescriptorImpl {
+
+
+      //--------------------------/
+     //- Class/Member Variables -/
+    //--------------------------/
+
+    /**
+     * Field _elementDefinition.
+     */
+    private boolean _elementDefinition;
+
+    /**
+     * Field _nsPrefix.
+     */
+    private java.lang.String _nsPrefix;
+
+    /**
+     * Field _nsURI.
+     */
+    private java.lang.String _nsURI;
+
+    /**
+     * Field _xmlName.
+     */
+    private java.lang.String _xmlName;
+
+
+      //----------------/
+     //- Constructors -/
+    //----------------/
+
+    public JSeqDescriptor() {
+        super();
+        _nsURI = "www.jalview.org";
+        _xmlName = "JSeq";
+        _elementDefinition = true;
+        
+        //-- set grouping compositor
+        setCompositorAsSequence();
+        org.exolab.castor.xml.util.XMLFieldDescriptorImpl  desc           = null;
+        org.exolab.castor.mapping.FieldHandler             handler        = null;
+        org.exolab.castor.xml.FieldValidator               fieldValidator = null;
+        //-- initialize attribute descriptors
+        
+        //-- _colour
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_colour", "colour", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                if (!target.hasColour()) { return null; }
+                return new java.lang.Integer(target.getColour());
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteColour();
+                        return;
+                    }
+                    target.setColour( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _colour
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
         }
-        return new java.lang.Integer(target.getColour());
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          // if null, use delete method for optional primitives
-          if (value == null)
-          {
-            target.deleteColour();
-            return;
-          }
-          target.setColour(((java.lang.Integer) value).intValue());
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
+        desc.setValidator(fieldValidator);
+        //-- _start
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_start", "start", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                if (!target.hasStart()) { return null; }
+                return new java.lang.Integer(target.getStart());
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    // ignore null values for non optional primitives
+                    if (value == null) { return; }
+                    
+                    target.setStart( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setRequired(true);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _start
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(1);
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
         }
-      }
-
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return null;
-      }
-    };
-    desc.setHandler(handler);
-    desc.setMultivalued(false);
-    addFieldDescriptor(desc);
-
-    // -- validation code for: _colour
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    { // -- local scope
-      org.exolab.castor.xml.validators.IntValidator typeValidator;
-      typeValidator = new org.exolab.castor.xml.validators.IntValidator();
-      fieldValidator.setValidator(typeValidator);
-      typeValidator.setMinInclusive(-2147483648);
-      typeValidator.setMaxInclusive(2147483647);
-    }
-    desc.setValidator(fieldValidator);
-    // -- _start
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            java.lang.Integer.TYPE, "_start", "start",
-            org.exolab.castor.xml.NodeType.Attribute);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        if (!target.hasStart())
-        {
-          return null;
+        desc.setValidator(fieldValidator);
+        //-- _end
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_end", "end", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                if (!target.hasEnd()) { return null; }
+                return new java.lang.Integer(target.getEnd());
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    // ignore null values for non optional primitives
+                    if (value == null) { return; }
+                    
+                    target.setEnd( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setRequired(true);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _end
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(1);
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
         }
-        return new java.lang.Integer(target.getStart());
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          // ignore null values for non optional primitives
-          if (value == null)
-          {
-            return;
-          }
-
-          target.setStart(((java.lang.Integer) value).intValue());
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
+        desc.setValidator(fieldValidator);
+        //-- _id
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.String.class, "_id", "id", org.exolab.castor.xml.NodeType.Attribute);
+        desc.setImmutable(true);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                return target.getId();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.setId( (java.lang.String) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setRequired(true);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _id
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(1);
+        { //-- local scope
+            org.exolab.castor.xml.validators.StringValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.StringValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setWhiteSpace("preserve");
         }
-      }
-
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return null;
-      }
-    };
-    desc.setHandler(handler);
-    desc.setRequired(true);
-    desc.setMultivalued(false);
-    addFieldDescriptor(desc);
-
-    // -- validation code for: _start
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    fieldValidator.setMinOccurs(1);
-    { // -- local scope
-      org.exolab.castor.xml.validators.IntValidator typeValidator;
-      typeValidator = new org.exolab.castor.xml.validators.IntValidator();
-      fieldValidator.setValidator(typeValidator);
-      typeValidator.setMinInclusive(-2147483648);
-      typeValidator.setMaxInclusive(2147483647);
-    }
-    desc.setValidator(fieldValidator);
-    // -- _end
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            java.lang.Integer.TYPE, "_end", "end",
-            org.exolab.castor.xml.NodeType.Attribute);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        if (!target.hasEnd())
-        {
-          return null;
+        desc.setValidator(fieldValidator);
+        //-- _hidden
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Boolean.TYPE, "_hidden", "hidden", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                if (!target.hasHidden()) { return null; }
+                return (target.getHidden() ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE);
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteHidden();
+                        return;
+                    }
+                    target.setHidden( ((java.lang.Boolean) value).booleanValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _hidden
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.BooleanValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.BooleanValidator();
+            fieldValidator.setValidator(typeValidator);
         }
-        return new java.lang.Integer(target.getEnd());
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          // ignore null values for non optional primitives
-          if (value == null)
-          {
-            return;
-          }
-
-          target.setEnd(((java.lang.Integer) value).intValue());
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
+        desc.setValidator(fieldValidator);
+        //-- _viewreference
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Boolean.TYPE, "_viewreference", "viewreference", org.exolab.castor.xml.NodeType.Attribute);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                if (!target.hasViewreference()) { return null; }
+                return (target.getViewreference() ? java.lang.Boolean.TRUE : java.lang.Boolean.FALSE);
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    // if null, use delete method for optional primitives 
+                    if (value == null) {
+                        target.deleteViewreference();
+                        return;
+                    }
+                    target.setViewreference( ((java.lang.Boolean) value).booleanValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _viewreference
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.BooleanValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.BooleanValidator();
+            fieldValidator.setValidator(typeValidator);
         }
-      }
-
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return null;
-      }
-    };
-    desc.setHandler(handler);
-    desc.setRequired(true);
-    desc.setMultivalued(false);
-    addFieldDescriptor(desc);
-
-    // -- validation code for: _end
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    fieldValidator.setMinOccurs(1);
-    { // -- local scope
-      org.exolab.castor.xml.validators.IntValidator typeValidator;
-      typeValidator = new org.exolab.castor.xml.validators.IntValidator();
-      fieldValidator.setValidator(typeValidator);
-      typeValidator.setMinInclusive(-2147483648);
-      typeValidator.setMaxInclusive(2147483647);
-    }
-    desc.setValidator(fieldValidator);
-    // -- _id
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            java.lang.String.class, "_id", "id",
-            org.exolab.castor.xml.NodeType.Attribute);
-    desc.setImmutable(true);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        return target.getId();
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          target.setId((java.lang.String) value);
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
+        desc.setValidator(fieldValidator);
+        //-- initialize element descriptors
+        
+        //-- _featuresList
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(jalview.schemabinding.version2.Features.class, "_featuresList", "features", org.exolab.castor.xml.NodeType.Element);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                return target.getFeatures();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.addFeatures( (jalview.schemabinding.version2.Features) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public void resetValue(Object object) throws IllegalStateException, IllegalArgumentException {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.removeAllFeatures();
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return new jalview.schemabinding.version2.Features();
+            }
+        };
+        desc.setHandler(handler);
+        desc.setNameSpaceURI("www.jalview.org");
+        desc.setMultivalued(true);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _featuresList
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(0);
+        { //-- local scope
         }
-      }
-
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return null;
-      }
-    };
-    desc.setHandler(handler);
-    desc.setRequired(true);
-    desc.setMultivalued(false);
-    addFieldDescriptor(desc);
-
-    // -- validation code for: _id
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    fieldValidator.setMinOccurs(1);
-    { // -- local scope
-      org.exolab.castor.xml.validators.StringValidator typeValidator;
-      typeValidator = new org.exolab.castor.xml.validators.StringValidator();
-      fieldValidator.setValidator(typeValidator);
-      typeValidator.setWhiteSpace("preserve");
-    }
-    desc.setValidator(fieldValidator);
-    // -- _hidden
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            java.lang.Boolean.TYPE, "_hidden", "hidden",
-            org.exolab.castor.xml.NodeType.Attribute);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        if (!target.hasHidden())
-        {
-          return null;
+        desc.setValidator(fieldValidator);
+        //-- _pdbidsList
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(jalview.schemabinding.version2.Pdbids.class, "_pdbidsList", "pdbids", org.exolab.castor.xml.NodeType.Element);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                return target.getPdbids();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.addPdbids( (jalview.schemabinding.version2.Pdbids) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public void resetValue(Object object) throws IllegalStateException, IllegalArgumentException {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.removeAllPdbids();
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return new jalview.schemabinding.version2.Pdbids();
+            }
+        };
+        desc.setHandler(handler);
+        desc.setNameSpaceURI("www.jalview.org");
+        desc.setMultivalued(true);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _pdbidsList
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(0);
+        { //-- local scope
         }
-        return (target.getHidden() ? java.lang.Boolean.TRUE
-                : java.lang.Boolean.FALSE);
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          // if null, use delete method for optional primitives
-          if (value == null)
-          {
-            target.deleteHidden();
-            return;
-          }
-          target.setHidden(((java.lang.Boolean) value).booleanValue());
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
+        desc.setValidator(fieldValidator);
+        //-- _hiddenSequencesList
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.Integer.TYPE, "_hiddenSequencesList", "hiddenSequences", org.exolab.castor.xml.NodeType.Element);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                return target.getHiddenSequences();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    // ignore null values for non optional primitives
+                    if (value == null) { return; }
+                    
+                    target.addHiddenSequences( ((java.lang.Integer) value).intValue());
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public void resetValue(Object object) throws IllegalStateException, IllegalArgumentException {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.removeAllHiddenSequences();
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setNameSpaceURI("www.jalview.org");
+        desc.setMultivalued(true);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _hiddenSequencesList
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(0);
+        { //-- local scope
+            org.exolab.castor.xml.validators.IntValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.IntValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setMinInclusive(-2147483648);
+            typeValidator.setMaxInclusive(2147483647);
         }
-      }
-
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return null;
-      }
-    };
-    desc.setHandler(handler);
-    desc.setMultivalued(false);
-    addFieldDescriptor(desc);
-
-    // -- validation code for: _hidden
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    { // -- local scope
-      org.exolab.castor.xml.validators.BooleanValidator typeValidator;
-      typeValidator = new org.exolab.castor.xml.validators.BooleanValidator();
-      fieldValidator.setValidator(typeValidator);
-    }
-    desc.setValidator(fieldValidator);
-    // -- _viewreference
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            java.lang.Boolean.TYPE, "_viewreference", "viewreference",
-            org.exolab.castor.xml.NodeType.Attribute);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        if (!target.hasViewreference())
-        {
-          return null;
+        desc.setValidator(fieldValidator);
+        //-- _rnaViewerList
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(jalview.schemabinding.version2.RnaViewer.class, "_rnaViewerList", "rnaViewer", org.exolab.castor.xml.NodeType.Element);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                return target.getRnaViewer();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.addRnaViewer( (jalview.schemabinding.version2.RnaViewer) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public void resetValue(Object object) throws IllegalStateException, IllegalArgumentException {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.removeAllRnaViewer();
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return new jalview.schemabinding.version2.RnaViewer();
+            }
+        };
+        desc.setHandler(handler);
+        desc.setNameSpaceURI("www.jalview.org");
+        desc.setMultivalued(true);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _rnaViewerList
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        fieldValidator.setMinOccurs(0);
+        { //-- local scope
         }
-        return (target.getViewreference() ? java.lang.Boolean.TRUE
-                : java.lang.Boolean.FALSE);
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          // if null, use delete method for optional primitives
-          if (value == null)
-          {
-            target.deleteViewreference();
-            return;
-          }
-          target.setViewreference(((java.lang.Boolean) value)
-                  .booleanValue());
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
+        desc.setValidator(fieldValidator);
+        //-- _hmmerProfile
+        desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(java.lang.String.class, "_hmmerProfile", "hmmerProfile", org.exolab.castor.xml.NodeType.Element);
+        desc.setImmutable(true);
+        handler = new org.exolab.castor.xml.XMLFieldHandler() {
+            public java.lang.Object getValue( java.lang.Object object ) 
+                throws IllegalStateException
+            {
+                JSeq target = (JSeq) object;
+                return target.getHmmerProfile();
+            }
+            public void setValue( java.lang.Object object, java.lang.Object value) 
+                throws IllegalStateException, IllegalArgumentException
+            {
+                try {
+                    JSeq target = (JSeq) object;
+                    target.setHmmerProfile( (java.lang.String) value);
+                } catch (java.lang.Exception ex) {
+                    throw new IllegalStateException(ex.toString());
+                }
+            }
+            public java.lang.Object newInstance(java.lang.Object parent) {
+                return null;
+            }
+        };
+        desc.setHandler(handler);
+        desc.setNameSpaceURI("www.jalview.org");
+        desc.setMultivalued(false);
+        addFieldDescriptor(desc);
+        
+        //-- validation code for: _hmmerProfile
+        fieldValidator = new org.exolab.castor.xml.FieldValidator();
+        { //-- local scope
+            org.exolab.castor.xml.validators.StringValidator typeValidator;
+            typeValidator = new org.exolab.castor.xml.validators.StringValidator();
+            fieldValidator.setValidator(typeValidator);
+            typeValidator.setWhiteSpace("preserve");
         }
-      }
-
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return null;
-      }
-    };
-    desc.setHandler(handler);
-    desc.setMultivalued(false);
-    addFieldDescriptor(desc);
-
-    // -- validation code for: _viewreference
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    { // -- local scope
-      org.exolab.castor.xml.validators.BooleanValidator typeValidator;
-      typeValidator = new org.exolab.castor.xml.validators.BooleanValidator();
-      fieldValidator.setValidator(typeValidator);
+        desc.setValidator(fieldValidator);
     }
-    desc.setValidator(fieldValidator);
-    // -- initialize element descriptors
 
-    // -- _featuresList
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            jalview.schemabinding.version2.Features.class, "_featuresList",
-            "features", org.exolab.castor.xml.NodeType.Element);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        return target.getFeatures();
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          target.addFeatures((jalview.schemabinding.version2.Features) value);
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
-        }
-      }
-
-      public void resetValue(Object object) throws IllegalStateException,
-              IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          target.removeAllFeatures();
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
-        }
-      }
 
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return new jalview.schemabinding.version2.Features();
-      }
-    };
-    desc.setHandler(handler);
-    desc.setNameSpaceURI("www.jalview.org");
-    desc.setMultivalued(true);
-    addFieldDescriptor(desc);
+      //-----------/
+     //- Methods -/
+    //-----------/
 
-    // -- validation code for: _featuresList
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    fieldValidator.setMinOccurs(0);
-    { // -- local scope
+    /**
+     * Method getAccessMode.
+     * 
+     * @return the access mode specified for this class.
+     */
+    public org.exolab.castor.mapping.AccessMode getAccessMode(
+    ) {
+        return null;
     }
-    desc.setValidator(fieldValidator);
-    // -- _pdbidsList
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            jalview.schemabinding.version2.Pdbids.class, "_pdbidsList",
-            "pdbids", org.exolab.castor.xml.NodeType.Element);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        return target.getPdbids();
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          target.addPdbids((jalview.schemabinding.version2.Pdbids) value);
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
-        }
-      }
-
-      public void resetValue(Object object) throws IllegalStateException,
-              IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          target.removeAllPdbids();
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
-        }
-      }
 
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return new jalview.schemabinding.version2.Pdbids();
-      }
-    };
-    desc.setHandler(handler);
-    desc.setNameSpaceURI("www.jalview.org");
-    desc.setMultivalued(true);
-    addFieldDescriptor(desc);
-
-    // -- validation code for: _pdbidsList
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    fieldValidator.setMinOccurs(0);
-    { // -- local scope
+    /**
+     * Method getIdentity.
+     * 
+     * @return the identity field, null if this class has no
+     * identity.
+     */
+    public org.exolab.castor.mapping.FieldDescriptor getIdentity(
+    ) {
+        return super.getIdentity();
     }
-    desc.setValidator(fieldValidator);
-    // -- _hiddenSequencesList
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            java.lang.Integer.TYPE, "_hiddenSequencesList",
-            "hiddenSequences", org.exolab.castor.xml.NodeType.Element);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        return target.getHiddenSequences();
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          // ignore null values for non optional primitives
-          if (value == null)
-          {
-            return;
-          }
-
-          target.addHiddenSequences(((java.lang.Integer) value).intValue());
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
-        }
-      }
 
-      public void resetValue(Object object) throws IllegalStateException,
-              IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          target.removeAllHiddenSequences();
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
-        }
-      }
-
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return null;
-      }
-    };
-    desc.setHandler(handler);
-    desc.setNameSpaceURI("www.jalview.org");
-    desc.setMultivalued(true);
-    addFieldDescriptor(desc);
-
-    // -- validation code for: _hiddenSequencesList
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    fieldValidator.setMinOccurs(0);
-    { // -- local scope
-      org.exolab.castor.xml.validators.IntValidator typeValidator;
-      typeValidator = new org.exolab.castor.xml.validators.IntValidator();
-      fieldValidator.setValidator(typeValidator);
-      typeValidator.setMinInclusive(-2147483648);
-      typeValidator.setMaxInclusive(2147483647);
+    /**
+     * Method getJavaClass.
+     * 
+     * @return the Java class represented by this descriptor.
+     */
+    public java.lang.Class getJavaClass(
+    ) {
+        return jalview.schemabinding.version2.JSeq.class;
     }
-    desc.setValidator(fieldValidator);
-    // -- _rnaViewerList
-    desc = new org.exolab.castor.xml.util.XMLFieldDescriptorImpl(
-            jalview.schemabinding.version2.RnaViewer.class,
-            "_rnaViewerList", "rnaViewer",
-            org.exolab.castor.xml.NodeType.Element);
-    handler = new org.exolab.castor.xml.XMLFieldHandler()
-    {
-      public java.lang.Object getValue(java.lang.Object object)
-              throws IllegalStateException
-      {
-        JSeq target = (JSeq) object;
-        return target.getRnaViewer();
-      }
-
-      public void setValue(java.lang.Object object, java.lang.Object value)
-              throws IllegalStateException, IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          target.addRnaViewer((jalview.schemabinding.version2.RnaViewer) value);
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
-        }
-      }
-
-      public void resetValue(Object object) throws IllegalStateException,
-              IllegalArgumentException
-      {
-        try
-        {
-          JSeq target = (JSeq) object;
-          target.removeAllRnaViewer();
-        } catch (java.lang.Exception ex)
-        {
-          throw new IllegalStateException(ex.toString());
-        }
-      }
-
-      public java.lang.Object newInstance(java.lang.Object parent)
-      {
-        return new jalview.schemabinding.version2.RnaViewer();
-      }
-    };
-    desc.setHandler(handler);
-    desc.setNameSpaceURI("www.jalview.org");
-    desc.setMultivalued(true);
-    addFieldDescriptor(desc);
 
-    // -- validation code for: _rnaViewerList
-    fieldValidator = new org.exolab.castor.xml.FieldValidator();
-    fieldValidator.setMinOccurs(0);
-    { // -- local scope
+    /**
+     * Method getNameSpacePrefix.
+     * 
+     * @return the namespace prefix to use when marshaling as XML.
+     */
+    public java.lang.String getNameSpacePrefix(
+    ) {
+        return _nsPrefix;
     }
-    desc.setValidator(fieldValidator);
-  }
 
-  // -----------/
-  // - Methods -/
-  // -----------/
-
-  /**
-   * Method getAccessMode.
-   * 
-   * @return the access mode specified for this class.
-   */
-  public org.exolab.castor.mapping.AccessMode getAccessMode()
-  {
-    return null;
-  }
-
-  /**
-   * Method getIdentity.
-   * 
-   * @return the identity field, null if this class has no identity.
-   */
-  public org.exolab.castor.mapping.FieldDescriptor getIdentity()
-  {
-    return super.getIdentity();
-  }
-
-  /**
-   * Method getJavaClass.
-   * 
-   * @return the Java class represented by this descriptor.
-   */
-  public java.lang.Class getJavaClass()
-  {
-    return jalview.schemabinding.version2.JSeq.class;
-  }
-
-  /**
-   * Method getNameSpacePrefix.
-   * 
-   * @return the namespace prefix to use when marshaling as XML.
-   */
-  public java.lang.String getNameSpacePrefix()
-  {
-    return _nsPrefix;
-  }
-
-  /**
-   * Method getNameSpaceURI.
-   * 
-   * @return the namespace URI used when marshaling and unmarshaling as XML.
-   */
-  public java.lang.String getNameSpaceURI()
-  {
-    return _nsURI;
-  }
+    /**
+     * Method getNameSpaceURI.
+     * 
+     * @return the namespace URI used when marshaling and
+     * unmarshaling as XML.
+     */
+    public java.lang.String getNameSpaceURI(
+    ) {
+        return _nsURI;
+    }
 
-  /**
-   * Method getValidator.
-   * 
-   * @return a specific validator for the class described by this
-   *         ClassDescriptor.
-   */
-  public org.exolab.castor.xml.TypeValidator getValidator()
-  {
-    return this;
-  }
+    /**
+     * Method getValidator.
+     * 
+     * @return a specific validator for the class described by this
+     * ClassDescriptor.
+     */
+    public org.exolab.castor.xml.TypeValidator getValidator(
+    ) {
+        return this;
+    }
 
-  /**
-   * Method getXMLName.
-   * 
-   * @return the XML Name for the Class being described.
-   */
-  public java.lang.String getXMLName()
-  {
-    return _xmlName;
-  }
+    /**
+     * Method getXMLName.
+     * 
+     * @return the XML Name for the Class being described.
+     */
+    public java.lang.String getXMLName(
+    ) {
+        return _xmlName;
+    }
 
-  /**
-   * Method isElementDefinition.
-   * 
-   * @return true if XML schema definition of this Class is that of a global
-   *         element or element with anonymous type definition.
-   */
-  public boolean isElementDefinition()
-  {
-    return _elementDefinition;
-  }
+    /**
+     * Method isElementDefinition.
+     * 
+     * @return true if XML schema definition of this Class is that
+     * of a global
+     * element or element with anonymous type definition.
+     */
+    public boolean isElementDefinition(
+    ) {
+        return _elementDefinition;
+    }
 
 }
diff --git a/src/jalview/schemes/HmmerColourScheme.java b/src/jalview/schemes/HmmerColourScheme.java
new file mode 100644 (file)
index 0000000..0f81ec1
--- /dev/null
@@ -0,0 +1,197 @@
+package jalview.schemes;
+
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+import jalview.util.ColorUtils;
+import jalview.util.Comparison;
+
+import java.awt.Color;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Base class for colour schemes based on a selected Hidden Markov Model. The
+ * colour is with reference to an HMM consensus sequence and HMM profile
+ * <ul>
+ * <li>white for a gap</li>
+ * <li>red for an insertion (position is gapped in the HMM consensus)</li>
+ * <li>orange for negative information content</li>
+ * <li>white to blue for increasing information content</li>
+ * </ul>
+ * where information content is the log ratio
+ * 
+ * <pre>
+ *   log(profile match emission probability / residue background probability)
+ * </pre>
+ * 
+ * Sub-class implementations use either global ('Uniprot') or local
+ * ('alignment') background frequencies.
+ * 
+ * @author tzvanaalten
+ * @author gmcarstairs
+ */
+public abstract class HmmerColourScheme extends ResidueColourScheme
+{
+  private static final Color INSERTION_COLOUR = new Color(230, 0, 0); // reddish
+
+  /*
+   * the aligned HMM consensus sequence to use as reference for colouring
+   */
+  private SequenceI hmmSeq;
+
+  private HiddenMarkovModel hmm;
+
+  private Map<Character, Float> frequencies;
+
+  /**
+   * Constructor given a list of Hidden Markov Model consensus sequences. The
+   * first sequence provides the HMM profile from which we can read the emission
+   * probabilities that determine the colour.
+   * 
+   * @param hmmSeqs
+   */
+  public HmmerColourScheme(List<SequenceI> hmmSeqs)
+  {
+    hmmSeq = hmmSeqs.isEmpty() ? null : hmmSeqs.get(0);
+    hmm = hmmSeq == null ? null : hmmSeq.getHMM();
+  }
+
+  /**
+   * Default constructor (required by ColourSchemes.loadColourSchemes)
+   */
+  public HmmerColourScheme()
+  {
+  }
+
+  @Override
+  public Color findColour(char symbol, int column, SequenceI seq,
+          String consensusResidue, float pid)
+  {
+    return findColour(symbol, column);
+  }
+
+  /**
+   * Returns the colour at a particular symbol at a column in the alignment:
+   * <ul>
+   * <li>white for a gap</li>
+   * <li>red for an insertion</li>
+   * <li>orange for negative information content</li>
+   * <li>white to blue for increasing information content</li>
+   * </ul>
+   * 
+   * @param symbol
+   * @param column
+   * @return
+   */
+  private Color findColour(char symbol, int column)
+  {
+    if (getHmm() == null || Comparison.isGap(symbol))
+    {
+      return Color.white;
+    }
+    if (Comparison.isGap(hmmSeq.getCharAt(column)))
+    {
+      return INSERTION_COLOUR;
+    }
+    if (Character.isLowerCase(symbol))
+    {
+      symbol = Character.toUpperCase(symbol);
+    }
+
+    final double prob = getHmm().getMatchEmissionProbability(column,
+            symbol);
+
+    Float freq = 0f;
+
+    if (!frequencies.containsKey(symbol))
+    {
+      return Color.WHITE;
+    }
+    else
+    {
+      freq = frequencies.get(symbol);
+    }
+
+    /*
+     * Orange if match emission probability is less than background probability
+     */
+    double infoRatio = prob / freq.floatValue();
+    Color colour = Color.ORANGE;
+    if (infoRatio >= 1)
+    {
+      /*
+       * log-scale graduated shade of blue if prob is greater than background  
+       */
+      float infoLog = (float) Math.log(infoRatio);
+      colour = ColorUtils.getGraduatedColour(infoLog, 0, Color.WHITE,
+              getMaxInformationScore(), Color.blue);
+    }
+
+    return colour;
+  }
+
+  /**
+   * Answers the maximum possible value of information score (log ratio), for
+   * use in scaling a graduated colour range
+   * 
+   * @return
+   */
+  abstract float getMaxInformationScore();
+
+  /**
+   * Answers a new colour scheme instance based on the HMM of the first sequence
+   * in ac that has an HMM
+   */
+  @Override
+  public ColourSchemeI getInstance(AnnotatedCollectionI ac,
+          Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
+  {
+    return newInstance(ac);
+  }
+
+  /**
+   * Answers a new instance of the colour scheme for the given HMM
+   * 
+   * @param ac
+   * @return
+   */
+  protected abstract HmmerColourScheme newInstance(AnnotatedCollectionI ac);
+
+  @Override
+  public boolean isSimple()
+  {
+    return false;
+  }
+
+  /**
+   * Answers true if the sequence collection has an HMM consensus sequence, else
+   * false
+   */
+  @Override
+  public boolean isApplicableTo(AnnotatedCollectionI ac)
+  {
+    return !ac.getHmmSequences().isEmpty();
+  }
+
+  protected Map<Character, Float> getFrequencies()
+  {
+    return frequencies;
+  }
+
+  protected void setFrequencies(Map<Character, Float> frequencies)
+  {
+    this.frequencies = frequencies;
+  }
+
+  protected HiddenMarkovModel getHmm()
+  {
+    return hmm;
+  }
+
+  protected SequenceI getHmmSequence()
+  {
+    return hmmSeq;
+  }
+}
diff --git a/src/jalview/schemes/HmmerGlobalBackground.java b/src/jalview/schemes/HmmerGlobalBackground.java
new file mode 100644 (file)
index 0000000..31bcadf
--- /dev/null
@@ -0,0 +1,61 @@
+package jalview.schemes;
+
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.SequenceCollectionI;
+
+/**
+ * An HMM colour scheme that uses global ('Uniprot') background frequencies for
+ * residues
+ * 
+ * @author tzvanaalten
+ */
+public class HmmerGlobalBackground extends HmmerColourScheme
+{
+  /*
+   * The highest possible log ratio is when match emission probability in
+   * the HMM model is 1, and background (for W) is 0.0109 giving
+   * log(1/0.0109) = log(91.743) = 4.519
+   */
+  private static final float MAX_LOG_RATIO = 4.519f;
+
+  /**
+   * Constructor given a sequence collection
+   * 
+   * @param ac
+   */
+  public HmmerGlobalBackground(SequenceCollectionI ac)
+  {
+    super(ac.getHmmSequences());
+    String alphabetType = getHmm() == null
+            ? ResidueProperties.ALPHABET_AMINO
+            : getHmm().getAlphabetType();
+    setFrequencies(
+            ResidueProperties.backgroundFrequencies.get(alphabetType));
+  }
+
+  /**
+   * Default constructor (required by ColourSchemes.loadColourSchemes)
+   */
+  public HmmerGlobalBackground()
+  {
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.HMMERU.toString();
+  }
+
+  @Override
+  protected HmmerColourScheme newInstance(AnnotatedCollectionI ac)
+  {
+    return new HmmerGlobalBackground(ac);
+  }
+
+  @Override
+  float getMaxInformationScore()
+  {
+    return MAX_LOG_RATIO;
+  }
+
+}
diff --git a/src/jalview/schemes/HmmerLocalBackground.java b/src/jalview/schemes/HmmerLocalBackground.java
new file mode 100644 (file)
index 0000000..2fe775c
--- /dev/null
@@ -0,0 +1,96 @@
+package jalview.schemes;
+
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.ResidueCount;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceI;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An HMM colour scheme that uses local (alignment or sub-group) background
+ * frequencies for residues
+ * 
+ * @author tzvanaalten
+ */
+public class HmmerLocalBackground extends HmmerColourScheme
+{
+  float logTotalCount;
+
+  /**
+   * Constructor given a sequence collection
+   * 
+   * @param ac
+   */
+  public HmmerLocalBackground(AnnotatedCollectionI ac)
+  {
+    super(ac.getHmmSequences());
+    countFrequencies(ac);
+  }
+
+  /**
+   * Default constructor (required by ColourSchemes.loadColourSchemes)
+   */
+  public HmmerLocalBackground()
+  {
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.HMMERA.toString();
+  }
+
+  /**
+   * Counts and stores the relative frequency of every residue in the alignment
+   * (apart from any HMM consensus sequences)
+   * 
+   * @param sc
+   */
+  public void countFrequencies(SequenceCollectionI sc)
+  {
+    // TODO or total counts in Consensus Profile (how do we get at it?)?
+    Map<Character, Float> freqs = new HashMap<>();
+
+    /*
+     * count symbols, excluding any HMM consensus sequences
+     */
+    ResidueCount counts = new ResidueCount();
+    List<SequenceI> seqs = sc.getSequences();
+    for (SequenceI seq : seqs)
+    {
+      if (!seq.hasHMMProfile())
+      {
+        for (char c : seq.getSequence())
+        {
+          counts.add(c);
+        }
+      }
+    }
+    int total = counts.getTotalResidueCount(); // excludes gaps
+
+    for (char symbol : counts.getSymbolCounts().symbols)
+    {
+      double freq = counts.getCount(symbol) / (double) total;
+      freqs.put(symbol, (float) freq);
+    }
+
+    setFrequencies(freqs);
+
+    logTotalCount = (float) Math.log(total);
+  }
+
+  @Override
+  float getMaxInformationScore()
+  {
+    return logTotalCount;
+  }
+
+  @Override
+  protected HmmerColourScheme newInstance(AnnotatedCollectionI ac)
+  {
+    return new HmmerLocalBackground(ac);
+  }
+}
index e1fc02d..357ea03 100644 (file)
@@ -42,7 +42,9 @@ public enum JalviewColourScheme
   Nucleotide("Nucleotide", NucleotideColourScheme.class),
   PurinePyrimidine("Purine/Pyrimidine", PurinePyrimidineColourScheme.class),
   RNAHelices("RNA Helices", RNAHelicesColour.class),
-  TCoffee("T-Coffee Scores", TCoffeeColourScheme.class);
+  TCoffee("T-Coffee Scores", TCoffeeColourScheme.class),
+  HMMERU("HMMER-Uniprot", HmmerGlobalBackground.class),
+  HMMERA("HMMER-Alignment", HmmerLocalBackground.class);
   // RNAInteraction("RNA Interaction type", RNAInteractionColourScheme.class)
 
   private String name;
index a4e6480..9b0489e 100755 (executable)
@@ -32,6 +32,13 @@ import java.util.Vector;
 
 public class ResidueProperties
 {
+  // alphabet names used in Hidden Markov Model files
+  public static final String ALPHABET_RNA = "RNA";
+
+  public static final String ALPHABET_DNA = "DNA";
+
+  public static final String ALPHABET_AMINO = "amino";
+
   // Stores residue codes/names and colours and other things
   public static final int[] aaIndex; // aaHash version 2.1.1 and below
 
@@ -48,6 +55,9 @@ public class ResidueProperties
   // lookup from modified amino acid (e.g. MSE) to canonical form (e.g. MET)
   public static final Map<String, String> modifications = new HashMap<>();
 
+  // residue background frequencies across different alphabets
+  public static final Map<String, Map<Character, Float>> backgroundFrequencies = new HashMap<>();
+
   static
   {
     aaIndex = new int[255];
@@ -2517,6 +2527,58 @@ public class ResidueProperties
 
   }
 
+  static
+  {
+    Map<Character, Float> amino = new HashMap<>();
+    amino.put('A', 0.0826f);
+    amino.put('Q', 0.0393f);
+    amino.put('L', 0.0965f);
+    amino.put('S', 0.0661f);
+    amino.put('R', 0.0553f);
+    amino.put('E', 0.0674f);
+    amino.put('K', 0.0582f);
+    amino.put('T', 0.0535f);
+    amino.put('N', 0.0406f);
+    amino.put('G', 0.0708f);
+    amino.put('M', 0.0241f);
+    amino.put('W', 0.0109f);
+    amino.put('D', 0.0546f);
+    amino.put('H', 0.0227f);
+    amino.put('F', 0.0386f);
+    amino.put('Y', 0.0292f);
+    amino.put('C', 0.0137f);
+    amino.put('I', 0.0593f);
+    amino.put('P', 0.0472f);
+    amino.put('V', 0.0686f);
+    backgroundFrequencies.put(ALPHABET_AMINO, amino);
+    // todo: these don't match https://www.ebi.ac.uk/uniprot/TrEMBLstats - what
+    // are they?
+  }
+
+  // TODO get correct frequencies
+
+  static
+  {
+    Map<Character, Float> dna = new HashMap<>();
+    dna.put('A', 0.25f);
+    dna.put('C', 0.25f);
+    dna.put('T', 0.25f);
+    dna.put('G', 0.25f);
+    backgroundFrequencies.put(ALPHABET_DNA, dna);
+
+  }
+
+  static
+  {
+    Map<Character, Float> rna = new HashMap<>();
+    rna.put('A', 0.25f);
+    rna.put('C', 0.25f);
+    rna.put('T', 0.25f);
+    rna.put('G', 0.25f);
+    backgroundFrequencies.put(ALPHABET_RNA, rna);
+
+  }
+
   public static String getCanonicalAminoAcid(String aA)
   {
     String canonical = modifications.get(aA);
diff --git a/src/jalview/util/FileUtils.java b/src/jalview/util/FileUtils.java
new file mode 100644 (file)
index 0000000..1684763
--- /dev/null
@@ -0,0 +1,78 @@
+package jalview.util;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Miscellaneous file-related functions
+ */
+public final class FileUtils
+{
+
+  /**
+   * Answers the executable file for the given command, or null if not found or
+   * not executable. The path to the executable is the command name prefixed by
+   * the given folder path, optionally with .exe appended.
+   * 
+   * @param cmd
+   *          command short name, for example hmmbuild
+   * @param binaryPath
+   *          parent folder for the executable
+   * @return
+   */
+  public static File getExecutable(String cmd, String binaryPath)
+  {
+    File file = new File(binaryPath, cmd);
+    if (!file.canExecute())
+    {
+      file = new File(binaryPath, cmd + ".exe");
+      {
+        if (!file.canExecute())
+        {
+          file = null;
+        }
+      }
+    }
+    return file;
+  }
+
+  /**
+   * Answers the path to the folder containing the given executable file, by
+   * searching the PATH environment variable. Answers null if no such executable
+   * can be found.
+   * 
+   * @param cmd
+   * @return
+   */
+  public static String getPathTo(String cmd)
+  {
+    String paths = System.getenv("PATH");
+    // backslash is to escape regular expression argument
+    for (String path : paths.split("\\" + File.pathSeparator))
+    {
+      if (getExecutable(cmd, path) != null)
+      {
+        return path;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * A convenience method to create a temporary file that is deleted on exit of
+   * the JVM
+   * 
+   * @param prefix
+   * @param suffix
+   * @return
+   * @throws IOException
+   */
+  public static File createTempFile(String prefix, String suffix)
+          throws IOException
+  {
+    File f = File.createTempFile(prefix, suffix);
+    f.deleteOnExit();
+    return f;
+  }
+
+}
diff --git a/src/jalview/util/HMMProbabilityDistributionAnalyser.java b/src/jalview/util/HMMProbabilityDistributionAnalyser.java
new file mode 100644 (file)
index 0000000..66ae552
--- /dev/null
@@ -0,0 +1,978 @@
+package jalview.util;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceI;
+import jalview.io.DataSourceType;
+import jalview.io.FileParse;
+import jalview.io.HMMFile;
+import jalview.io.StockholmFile;
+import jalview.schemes.ResidueProperties;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Scanner;
+import java.util.Vector;
+
+/**
+ * Processes probability data. The file indexes used in this program represent
+ * the index of the location of a family or hmm in their respective files,
+ * starting from 0.
+ * 
+ * @author TZVanaalten
+ *
+ */
+public class HMMProbabilityDistributionAnalyser
+{
+  AlignmentAnnotation reference = null;
+
+  Vector<SequenceI> sequences;
+
+  HiddenMarkovModel hmm;
+
+  // contains the raw data produced
+  List<ArrayList<Double>> raw = new ArrayList<>();
+
+  // contains binned data
+  Map<String, Double> binned = new HashMap<>();
+
+  // location of the family file
+  String families = "/media/sf_Shared_Folder/PFAM/Family/SeedFamilies.seed";
+
+  // location of the file containing the family-clan links
+  final static String FAMILIESTOCLAN = "/media/sf_Shared_Folder/PFAM/Family/Clanlinks.dat";
+
+  // location of the HMM file
+  String hmms = "/media/sf_Shared_Folder/PFAM/HMMs/Pfam-A.hmm";
+
+  // suffix for raw file
+  final static String RAW = "/Raw.csv";
+
+  // suffix for binned file
+  final static String BINNED = "/Binned.csv";
+
+  // normalisation scale
+  final static double SCALE = 1;
+
+  // current position in file
+  int currentFilePosition = 0;
+
+  final static String NL = "\n";
+
+  Random generator = new Random();
+
+  // current directory
+  String currentFolder;
+
+  boolean keepRaw = false;
+
+  /**
+   * Sets the working directory.
+   * 
+   * @param path
+   */
+  public void setFolder(String path)
+  {
+    currentFolder = path;
+  }
+
+  /**
+   * Moves a buffered reader forward in the file by a certain amount of entries.
+   * Each entry in the file is delimited by '//'.
+   * 
+   * @param index
+   *          The index of the location in the file.
+   * @param br
+   * @throws IOException
+   */
+  public void moveLocationBy(int index, BufferedReader br)
+          throws IOException
+  {
+    for (int i = 0; i < index; i++)
+    {
+      String line = br.readLine();
+      while (!"//".equals(line))
+      {
+        line = br.readLine();
+
+      }
+    }
+
+  }
+  
+  /**
+   * Analyses a specified number of families and then saves the data. Before
+   * analysing the data, the previous saved data will be imported and after
+   * analysing this, the data is exported back into the file. The file must be
+   * in flat file format.
+   * 
+   * @param increments
+   *          The number of families to read before saving.
+   * @throws IOException
+   */
+  public void run(int increments, boolean keepRawData) throws IOException
+  {
+    keepRaw = keepRawData;
+    try
+    {
+      readPreviousData(currentFolder);
+      BufferedReader posReader = new BufferedReader(
+              new FileReader(currentFolder + "/CurrentPosition.txt"));
+
+      String line = posReader.readLine();
+      posReader.close();
+      currentFilePosition = Integer.parseInt(line);
+    } catch (Exception e)
+    {
+      System.out.println("No previous data found");
+    }
+
+
+
+    BufferedReader inputSTO = new BufferedReader(new FileReader(families));
+    BufferedReader inputHMM = new BufferedReader(new FileReader(hmms));
+
+
+
+    moveLocationBy(currentFilePosition, inputHMM);
+    moveLocationBy(currentFilePosition, inputSTO);
+
+    int filesRead = 0;
+    int i = 0;
+    while (filesRead < increments)
+    {
+
+      readStockholm(inputSTO);
+
+      readHMM(inputHMM);
+
+        int count = countValidResidues();
+        processData(count);
+        filesRead++;
+
+      currentFilePosition++;
+      System.out.println(i);
+      i++;
+    }
+
+    PrintWriter p = new PrintWriter(
+            new File(currentFolder + "/CurrentPosition.txt"));
+    p.print(currentFilePosition);
+    p.close();
+    exportData(currentFolder);
+    raw.clear();
+    binned.clear();
+
+  }
+
+  /**
+   * Analyses all families and then saves the data. Before analysing the data,
+   * the previous saved data will be imported and after analysing this, the data
+   * is exported back into the file. The file must be in flat file format.
+   * 
+   * @param increments
+   *          The number of families to read before saving.
+   * @throws IOException
+   */
+  public void runToEnd(int minCount, int maxCount, boolean keepRawData,
+          boolean forClans)
+          throws IOException
+  {
+    keepRaw = keepRawData;
+    BufferedReader inputSTO = null;
+    BufferedReader inputHMM = null;
+    int size = 0;
+    int files = 1;
+    try
+    {
+    if (forClans)
+    {
+        files = 603;
+    }
+    int filesRead = 0;
+    for (int clan = 0; clan < files; clan++)
+    {
+      System.out.println(clan);
+      String clanPath = "";
+      int numberOfFamilies = 0;
+      if (forClans)
+      {
+        clanPath = currentFolder + "/Clan" + clan;
+          if (!new File(clanPath).exists())
+          {
+            continue;
+          }
+        BufferedReader famCountReader = new BufferedReader(
+                new FileReader(clanPath + "/NumberOfFamilies.txt"));
+        numberOfFamilies = Integer.parseInt(famCountReader.readLine());
+      }
+      else
+      {
+        numberOfFamilies = 1;
+      }
+      
+      for (int fam = 0; fam < numberOfFamilies; fam++)
+      {
+        if (forClans)
+        {
+          families = clanPath + "/Families/Fam" + fam + ".sto";
+          hmms = clanPath + "/HMMs/HMM" + fam + ".hmm";
+        }
+
+        inputSTO = new BufferedReader(new FileReader(families));
+        inputHMM = new BufferedReader(new FileReader(hmms));
+
+
+        int i = 0;
+        boolean endReached = atEnd(inputSTO);
+        while (!endReached)
+        {
+          readStockholm(inputSTO);
+          readHMM(inputHMM);
+
+        int count = countValidResidues();
+            if (count >= minCount && count < maxCount)
+            {
+              processData(count);
+            }
+        filesRead++;
+          System.out.println(filesRead);
+      endReached = atEnd(inputSTO);
+      }
+      }
+    }
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+    } finally
+    {
+      exportData(currentFolder);
+      raw.clear();
+      binned.clear();
+    }
+  }
+
+  /**
+   * Reads the previous data from both files
+   * 
+   * @param source
+   * @throws IOException
+   */
+  public void readPreviousData(String source) throws IOException
+  {
+    readBinned(source);
+    if (keepRaw)
+    {
+      readRaw(source);
+    }
+  }
+
+  /**
+   * Reads the previous data from the binned file.
+   * 
+   * @param source
+   * @throws IOException
+   */
+  public void readBinned(String source) throws IOException
+  {
+    BufferedReader input = new BufferedReader(
+            new FileReader(source + BINNED));
+    String line = input.readLine();
+    binned = new HashMap<>();
+    while (!("".equals(line) || line == null))
+    {
+      Scanner scanner = new Scanner(line);
+      scanner.useDelimiter(",");
+      String key = scanner.next();
+      String value = scanner.next();
+      binned.put(key, Double.valueOf(value));
+      scanner.close();
+      line = input.readLine();
+    }
+
+    input.close();
+  }
+
+  /**
+   * Reads the previous data from the raw file.
+   * 
+   * @param source
+   * @throws IOException
+   */
+  public void readRaw(String source) throws IOException
+  {
+    BufferedReader input = new BufferedReader(new FileReader(source + RAW));
+    String line = input.readLine();
+    if (line == null)
+    {
+      input.close();
+      return;
+    }
+    Scanner numberScanner = new Scanner(line);
+    numberScanner.useDelimiter(",");
+    raw = new ArrayList<>();
+    while (numberScanner.hasNext())
+    {
+      numberScanner.next();
+      raw.add(new ArrayList<Double>());
+    }
+    numberScanner.close();
+
+    line = input.readLine();
+    while (!("".equals(line) || line == null))
+    {
+      Scanner scanner = new Scanner(line);
+      scanner.useDelimiter(",");
+
+      int i = 0;
+      while (scanner.hasNext())
+      {
+        String value;
+        value = scanner.next();
+        if (!value.equals("EMPTY"))
+        {
+          raw.get(i).add(Double.parseDouble(value));
+        }
+        else
+        {
+          raw.get(i).add(null);
+        }
+
+        i++;
+      }
+      scanner.close();
+      line = input.readLine();
+    }
+
+    input.close();
+  }
+
+  /**
+   * Counts the number of valid residues in the sequence.
+   * 
+   * @return
+   */
+  public int countValidResidues()
+  {
+    int count = 0;
+
+    for (int width = 0; width < sequences.size(); width++)
+    {
+      for (int length = 1; length < hmm.getLength() + 1; length++)
+      {
+        char symbol;
+        int alignPos;
+        alignPos = hmm.getNodeMapPosition(length);
+
+        symbol = sequences.get(width).getCharAt(alignPos);
+        if (ResidueProperties.backgroundFrequencies.get("amino")
+                .containsKey(symbol))
+        {
+          count++;
+        }
+      }
+    }
+
+    return count;
+  }
+
+  /**
+   * Processes data, and stores it in both a raw and binned format.
+   * 
+   * @param count
+   */
+  public void processData(int count)
+  {
+    int rawPos = 0;
+    if (keepRaw)
+    {
+      raw.add(new ArrayList<Double>());
+      rawPos = raw.size() - 1;
+    }
+    Double total = 0d;
+    for (int width = 0; width < sequences.size(); width++)
+    {
+      for (int length = 1; length < hmm.getLength() + 1; length++)
+      {
+        char symbol;
+        int alignPos;
+        alignPos = hmm.getNodeMapPosition(length);
+        
+        symbol = sequences.get(width).getCharAt(alignPos);
+        if (ResidueProperties.backgroundFrequencies.get("amino")
+                .containsKey(symbol))
+        {
+          Double prob;
+          Float bfreq;
+          Double llr;
+          prob = hmm.getMatchEmissionProbability(alignPos, symbol);
+          bfreq = ResidueProperties.backgroundFrequencies.get("amino")
+                  .get(symbol);
+          if (prob == 0 || bfreq == 0)
+          {
+            System.out.println("error");
+          }
+          llr = Math.log(prob / bfreq);
+          if (keepRaw)
+          {
+            raw.get(rawPos).add(llr);
+          }
+
+          String output;
+          output = String.format("%.1f", llr);
+          total += Double.parseDouble(output);
+          if ("-0.0".equals(output))
+          {
+            output = "0.0";
+          }
+          if (binned.containsKey(output))
+          {
+            double prev = binned.get(output);
+            prev += (SCALE / count);
+            binned.put(output, prev);
+
+          }
+          else
+          {
+            binned.put(output, SCALE / count);
+          }
+        }
+      }
+    }
+    System.out.println(total / count);
+  }
+
+
+  /**
+   * Reads in the sequence data from a Stockholm file.
+   * 
+   * @param source
+   * @throws IOException
+   */
+  public void readStockholm(BufferedReader inputSTO) throws IOException
+  {
+    FileParse parserSTO = new FileParse(inputSTO, "", DataSourceType.FILE);
+    StockholmFile file = new StockholmFile(parserSTO);
+    Vector<AlignmentAnnotation> annots = file.getAnnotations();
+
+    for (AlignmentAnnotation annot : annots)
+    {
+      if (annot.label.contains("Reference"))
+      {
+        reference = annot;
+      }
+    }
+    sequences = file.getSeqs();
+  }
+
+  /**
+   * Reads in the HMM data from a HMMer file.
+   * 
+   * @param source
+   * @throws IOException
+   */
+  public void readHMM(BufferedReader inputHMM) throws IOException
+  {
+    FileParse parserHMM = new FileParse(inputHMM, "", DataSourceType.FILE);
+    HMMFile file = new HMMFile(parserHMM);
+    hmm = file.getHMM();
+
+
+  }
+
+  /**
+   * Exports both the binned and raw data into separate files.
+   * 
+   * @param location
+   * @throws FileNotFoundException
+   */
+  public void exportData(String location) throws FileNotFoundException
+  {
+    PrintWriter writerBin = new PrintWriter(new File(location + BINNED));
+    for (Map.Entry<String, Double> entry : binned.entrySet())
+    {
+      writerBin.println(entry.getKey() + "," + entry.getValue());
+    }
+    writerBin.close();
+    if (keepRaw)
+    {
+
+    PrintWriter writerRaw = new PrintWriter(new File(location + RAW));
+    
+    StringBuilder identifier = new StringBuilder();
+    
+    for (int i = 1; i < raw.size() + 1; i++)
+    {
+      identifier.append("Fam " + i + ",");
+    }
+    
+    writerRaw.println(identifier);
+    
+    boolean rowIsEmpty = false;
+    int row = 0;
+    while (!rowIsEmpty)
+    {
+      rowIsEmpty = true;
+      StringBuilder string = new StringBuilder();
+      for (int column = 0; column < raw.size(); column++)
+      {
+        if (raw.get(column).size() <= row)
+        {
+          string.append("EMPTY,");
+        }
+        else
+        {
+          string.append(raw.get(column).get(row) + ",");
+          rowIsEmpty = false;
+        }
+      }
+      row++;
+      writerRaw.println(string);
+    }
+    writerRaw.close();
+
+    }
+
+  }
+
+  /**
+   * Prints the specified family on the console.
+   * 
+   * @param index
+   * @throws IOException
+   */
+  public void printFam(int index) throws IOException
+  {
+    BufferedReader br = new BufferedReader(new FileReader(families));
+
+    moveLocationBy(index, br);
+
+    String line = br.readLine();
+
+    while (!"//".equals(line))
+    {
+      System.out.println(line);
+      line = br.readLine();
+    }
+    System.out.println(line);
+    br.close();
+
+  }
+
+  /**
+   * Prints the specified HMM on the console.
+   * 
+   * @param index
+   * @throws IOException
+   */
+  public void printHMM(int index) throws IOException
+  {
+    BufferedReader br = new BufferedReader(new FileReader(hmms));
+
+    moveLocationBy(index, br);
+
+    String line = br.readLine();
+
+    while (!"//".equals(line))
+    {
+      System.out.println(line);
+      line = br.readLine();
+    }
+    System.out.println(line);
+    br.close();
+
+  }
+
+  /**
+   * Prints the specified family to a .sto file.
+   * 
+   * @param index
+   * @throws IOException
+   */
+  public void exportFam(int index, String location) throws IOException
+  {
+    BufferedReader br = new BufferedReader(new FileReader(families));
+
+    moveLocationBy(index, br);
+
+    String line = br.readLine();
+    PrintWriter writer = new PrintWriter(
+            new FileOutputStream(new File(location), true));
+    while (!"//".equals(line))
+    {
+      writer.println(line);
+      line = br.readLine();
+    }
+    writer.println(line);
+    writer.close();
+    br.close();
+
+  }
+
+  public void exportFile(BufferedReader br, String location, boolean append)
+          throws IOException
+  {
+    String line = br.readLine();
+    PrintWriter writer = new PrintWriter(
+            new FileOutputStream(location, append));
+    while (!"//".equals(line))
+    {
+      writer.println(line);
+      line = br.readLine();
+    }
+    writer.println(line);
+    writer.close();
+
+
+  }
+
+  public String getHMMName(int index) throws IOException
+  {
+    String name;
+
+    BufferedReader nameFinder = new BufferedReader(new FileReader(hmms));
+
+    moveLocationBy(index, nameFinder);
+
+    nameFinder.readLine();
+
+    Scanner scanner = new Scanner(nameFinder.readLine());
+    name = scanner.next();
+    name = scanner.next();
+    scanner.close();
+    return name;
+  }
+
+  public String getFamilyName(int index) throws IOException
+  {
+    String name;
+
+    BufferedReader nameFinder = new BufferedReader(
+            new FileReader(families));
+
+    moveLocationBy(index, nameFinder);
+
+    nameFinder.readLine();
+
+    Scanner scanner = new Scanner(nameFinder.readLine());
+    name = scanner.next();
+    name = scanner.next();
+    name = scanner.next();
+    scanner.close();
+    return name;
+  }
+
+  /**
+   * Prints the specified family to a .hmm file.
+   * 
+   * @param index
+   * @throws IOException
+   */
+  public void exportHMM(int index, String location) throws IOException
+  {
+
+
+    BufferedReader br = new BufferedReader(new FileReader(hmms));
+
+    moveLocationBy(index, br);
+
+    String line = br.readLine();
+
+    PrintWriter writer = new PrintWriter(
+            new FileOutputStream(new File(location), true));
+    while (!"//".equals(line))
+    {
+      writer.println(line);
+      line = br.readLine();
+    }
+    writer.println(line);
+    writer.close();
+    br.close();
+
+  }
+  
+  /**
+   * Clears all raw, binned and current position data in the current directory.
+   * 
+   * @throws FileNotFoundException
+   */
+  public void clear() throws FileNotFoundException
+  {
+    PrintWriter pos = new PrintWriter(
+            currentFolder + "/CurrentPosition.txt");
+    pos.println("0");
+    
+    PrintWriter raw = new PrintWriter(currentFolder + RAW);
+    
+    PrintWriter bin = new PrintWriter(currentFolder + BINNED);
+    
+    pos.close();
+    bin.close();
+    raw.close();
+  }
+
+  public void sortIntoClans(String directory) throws IOException
+  {
+    BufferedReader clanFinder = new BufferedReader(new FileReader(FAMILIESTOCLAN));
+    BufferedReader familyReader = new BufferedReader(
+            new FileReader(families));
+    BufferedReader hmmReader = new BufferedReader(new FileReader(hmms));
+    int families = 0;
+    // moveLocationBy(7000, familyReader);
+    // moveLocationBy(7000, clanFinder);
+    // moveLocationBy(7000, hmmReader);
+    HashMap<String, Integer> clanIndexes = new HashMap<>();
+    ArrayList<Integer> familyCounts = new ArrayList<>();
+    int filePos = 0; 
+    int clanCount = 0;
+    String line;
+    line = clanFinder.readLine();
+    
+    while (!"".equals(line) && !" ".equals(line) && line != null)
+    {
+     String clanName;
+      boolean inClan = false;
+     while (!(line.indexOf("//") > -1))
+     {
+       
+      if (line.indexOf("#=GF CL") > -1)
+      {
+          families++;
+          System.out.println(families);
+          inClan = true;
+        Scanner scanner = new Scanner(line);
+        scanner.next();
+        scanner.next();
+        clanName = scanner.next();
+          scanner.close();
+        
+        if (!clanIndexes.containsKey(clanName))
+        {
+          clanIndexes.put(clanName, clanCount);
+            clanCount++;
+            familyCounts.add(0);
+        }
+
+
+          Integer clanI = clanIndexes.get(clanName);
+          String clanPath = directory + "/Clan" + clanI.toString();
+          createFolders(clanPath);
+
+          int index = clanIndexes.get(clanName);
+          exportFile(familyReader,
+                  clanPath + "/Families/Fam" + familyCounts.get(index)
+                          + ".sto",
+                  false);
+          exportFile(hmmReader,
+                  clanPath + "/HMMs/HMM" + familyCounts.get(index) + ".hmm",
+                  false);
+
+          int count = familyCounts.get(index);
+          count++;
+          familyCounts.set(index, count);
+      }
+        line = clanFinder.readLine();
+
+      }
+      if (!inClan)
+      {
+        moveLocationBy(1, familyReader);
+        moveLocationBy(1, hmmReader);
+      }
+      filePos++;
+      // System.out.println(filePos + " files read.");
+      line = clanFinder.readLine();
+
+     }
+    clanFinder.close();
+
+    for (int clan = 0; clan < clanCount; clan++)
+    {
+      PrintWriter writer = new PrintWriter(
+              directory + "/Clan" + clan + "/NumberOfFamilies.txt");
+      int count = familyCounts.get(clan);
+      writer.print(count);
+      writer.close();
+    }
+      
+    }
+
+  public String getFamilies()
+  {
+    return families;
+  }
+
+  public void setFamilies(String families)
+  {
+    this.families = currentFolder + families;
+  }
+
+  public String getHmms()
+  {
+    return hmms;
+  }
+
+  public void setHmms(String hmms)
+  {
+    this.hmms = currentFolder + hmms;
+  }
+    
+  public void alignWithinClan(String exportLocation, String clansLocation)
+          throws IOException, InterruptedException
+  {
+    int alignmentsExported = 0;
+    for (int clan = 0; clan < 604; clan++)
+    {
+      System.out.println(clan);
+      int famCount = 0;
+      String clanPath = clansLocation + "/Clan" + clan;
+      int numberOfFamilies;
+      BufferedReader br = new BufferedReader(
+              new FileReader(clanPath + "/NumberOfFamilies.txt"));
+      String line = br.readLine();
+      numberOfFamilies = Integer.parseInt(line);
+      br.close();
+      if (numberOfFamilies == 1)
+      {
+        continue;
+      }
+      final String commandExportLocation = exportLocation + "/Clan" + clan;
+      createFolders(commandExportLocation);
+      for (int family = 0; family < numberOfFamilies; family++)
+      {
+        famCount++;
+        ArrayList<Integer> indexes = new ArrayList<>();
+        for (int i = 0; i < numberOfFamilies; i++)
+        {
+          if (i != family)
+          {
+            indexes.add(i);
+          }
+        }
+
+        int hmmIndex = getRandom(indexes);
+        String famPath = clanPath + "/Families/Fam" + family + ".sto";
+        String hmmPath = clanPath + "/HMMs/HMM" + hmmIndex + ".hmm";
+        String command = "/media/sf_Shared_Folder/hmmer/binaries/hmmalign --mapali "
+                + clanPath + "/Families/Fam" + hmmIndex + ".sto"
+                + " --trim ";
+        command += hmmPath + " ";
+        command += famPath;
+        final int familyIndex = family;
+        final Process p = Runtime.getRuntime().exec(command);
+
+        new Thread(new Runnable()
+        {
+          @Override
+          public void run()
+          {
+            BufferedReader input = new BufferedReader(
+                    new InputStreamReader(p.getInputStream()));
+            String line = null;
+
+            try
+            {
+              PrintWriter writer = new PrintWriter(commandExportLocation
+                      + "/Families/Fam" + familyIndex + ".sto");
+              String lastLine = "";
+              boolean dataFound = false;
+              while ((line = input.readLine()) != null)
+              {
+                if (line.contains("#=GR") && !dataFound)
+                {
+                  writer.println(lastLine);
+                  dataFound = true;
+                }
+                if (line.contains("#") || dataFound || " ".equals(line)
+                        || "".equals(line) || "//".equals(line))
+                {
+                  writer.println(line);
+                }
+                lastLine = line;
+              }
+              writer.close();
+            } catch (IOException e)
+            {
+              e.printStackTrace();
+            }
+          }
+        }).start();
+
+        p.waitFor();
+
+        BufferedReader hmmExporter = new BufferedReader(
+                new FileReader(hmmPath));
+
+        exportFile(hmmExporter,
+                commandExportLocation + "/HMMs/HMM" + family + ".hmm",
+                false);
+
+        alignmentsExported++;
+
+
+      }
+      PrintWriter writer = new PrintWriter(
+              commandExportLocation + "/NumberOfFamilies.txt");
+      writer.print(famCount);
+      writer.close();
+    }
+
+  }
+
+  public boolean atEnd(BufferedReader br) throws IOException
+  {
+    boolean end = false;
+    br.mark(80);
+    String line = br.readLine();
+    if ("".equals(line) || line == null)
+    {
+      end = true;
+    }
+    br.reset();
+    return end;
+  }
+
+  public int getRandom(ArrayList<Integer> list)
+  {
+    if (!(list.size() > 0))
+    {
+      System.out.println("Error - size = " + list.size());
+    }
+    int index = generator.nextInt(list.size());
+    int value = list.get(index);
+    list.remove(index);
+    return value;
+  }
+
+  public void createFolders(String clanPath)
+  {
+    File clanFolder = new File(clanPath);
+    if (!clanFolder.exists())
+    {
+      clanFolder.mkdir();
+    }
+
+    File famFolder = new File(clanPath + "/Families");
+    File hmmFolder = new File(clanPath + "/HMMs");
+    if (!famFolder.exists())
+    {
+      famFolder.mkdir();
+      hmmFolder.mkdir();
+    }
+  }
+}
+
+
+
+
index 7f1abc4..60054f1 100644 (file)
@@ -1030,70 +1030,15 @@ public class MapList
 
     for (int[] range : map.getFromRanges())
     {
-      addRange(range, fromShifts);
+      MappingUtils.addRange(range, fromShifts);
     }
     for (int[] range : map.getToRanges())
     {
-      addRange(range, toShifts);
+      MappingUtils.addRange(range, toShifts);
     }
   }
 
   /**
-   * Adds the given range to a list of ranges. If the new range just extends
-   * existing ranges, the current endpoint is updated instead.
-   * 
-   * @param range
-   * @param addTo
-   */
-  static void addRange(int[] range, List<int[]> addTo)
-  {
-    /*
-     * list is empty - add to it!
-     */
-    if (addTo.size() == 0)
-    {
-      addTo.add(range);
-      return;
-    }
-
-    int[] last = addTo.get(addTo.size() - 1);
-    boolean lastForward = last[1] >= last[0];
-    boolean newForward = range[1] >= range[0];
-
-    /*
-     * contiguous range in the same direction - just update endpoint
-     */
-    if (lastForward == newForward && last[1] == range[0])
-    {
-      last[1] = range[1];
-      return;
-    }
-
-    /*
-     * next range starts at +1 in forward sense - update endpoint
-     */
-    if (lastForward && newForward && range[0] == last[1] + 1)
-    {
-      last[1] = range[1];
-      return;
-    }
-
-    /*
-     * next range starts at -1 in reverse sense - update endpoint
-     */
-    if (!lastForward && !newForward && range[0] == last[1] - 1)
-    {
-      last[1] = range[1];
-      return;
-    }
-
-    /*
-     * just add the new range
-     */
-    addTo.add(range);
-  }
-
-  /**
    * Returns true if mapping is from forward strand, false if from reverse
    * strand. Result is just based on the first 'from' range that is not a single
    * position. Default is true unless proven to be false. Behaviour is not well
index b552c21..cd8821d 100644 (file)
@@ -1020,4 +1020,59 @@ public final class MappingUtils
       }
     }
   }
+
+  /**
+   * Adds the given range to a list of ranges. If the new range just extends
+   * existing ranges, the current endpoint is updated instead.
+   * 
+   * @param range
+   * @param addTo
+   */
+  public static void addRange(int[] range, List<int[]> addTo)
+  {
+    /*
+     * list is empty - add to it!
+     */
+    if (addTo.size() == 0)
+    {
+      addTo.add(range);
+      return;
+    }
+  
+    int[] last = addTo.get(addTo.size() - 1);
+    boolean lastForward = last[1] >= last[0];
+    boolean newForward = range[1] >= range[0];
+  
+    /*
+     * contiguous range in the same direction - just update endpoint
+     */
+    if (lastForward == newForward && last[1] == range[0])
+    {
+      last[1] = range[1];
+      return;
+    }
+  
+    /*
+     * next range starts at +1 in forward sense - update endpoint
+     */
+    if (lastForward && newForward && range[0] == last[1] + 1)
+    {
+      last[1] = range[1];
+      return;
+    }
+  
+    /*
+     * next range starts at -1 in reverse sense - update endpoint
+     */
+    if (!lastForward && !newForward && range[0] == last[1] - 1)
+    {
+      last[1] = range[1];
+      return;
+    }
+  
+    /*
+     * just add the new range
+     */
+    addTo.add(range);
+  }
 }
index 2c74609..7c0e15d 100644 (file)
@@ -51,7 +51,7 @@ public class Platform
   }
 
   /**
-   * Check if we are on a Microsoft plaform...
+   * Check if we are on a Microsoft platform...
    * 
    * @return true if we have to cope with another platform variation
    */
diff --git a/src/jalview/util/ProbabilityAnalyserKickstarter.java b/src/jalview/util/ProbabilityAnalyserKickstarter.java
new file mode 100644 (file)
index 0000000..59c0a9f
--- /dev/null
@@ -0,0 +1,221 @@
+package jalview.util;
+
+import java.io.IOException;
+import java.util.Scanner;
+
+/**
+ * This class contains the brain of the analyser program, and contains a number
+ * of commands for the processing of data.
+ * 
+ * @author TZVanaalten
+ *
+ */
+
+public class ProbabilityAnalyserKickstarter
+{
+
+  public static void main(String[] args)
+          throws IOException, InterruptedException
+  {
+
+    // this does all of the processing
+    HMMProbabilityDistributionAnalyser analyser = new HMMProbabilityDistributionAnalyser();
+
+    boolean running = true;
+    System.out.println("ACTIVATED");
+    while (running)
+    {
+      Scanner keyboard = new Scanner(System.in);
+      String command = keyboard.nextLine();
+
+      Scanner inputScanner = new Scanner(command);
+      // prints family to console. Syntax is printFam <index>
+      if (command.indexOf("printFam") > -1)
+      {
+        try
+        {
+          inputScanner.next();
+          int index = inputScanner.nextInt();
+          analyser.printFam(index);
+          continue;
+        } catch (Exception e)
+        {
+          System.out.println("Command failed");
+        }
+
+      }
+      // prints HMM to console. Syntax is printHMM <index>
+      if (command.indexOf("printHMM") > -1)
+      {
+        try
+        {
+        inputScanner.next();
+        int index = inputScanner.nextInt();
+        analyser.printHMM(index);
+        continue;
+        } catch (Exception e)
+        {
+          System.out.println("Command failed");
+        }
+      }
+      // prints family to file in current folder. Syntax is exportFam <index>.
+      if (command.indexOf("exportFam") > -1)
+      {
+        try
+        {
+        inputScanner.next();
+        int index = inputScanner.nextInt();
+          String location = inputScanner.next();
+          analyser.exportFam(index, location);
+        continue;
+        } catch (Exception e)
+        {
+          System.out.println("Command failed");
+        }
+      }
+      // prints HMM to file in current folder. Syntax is exportHMM <index>.
+      if (command.indexOf("exportHMM") > -1)
+      {
+        try
+        {
+        inputScanner.next();
+        int index = inputScanner.nextInt();
+          String location = inputScanner.next();
+          analyser.exportHMM(index, location);
+        continue;
+        } catch (Exception e)
+        {
+          System.out.println("Command failed");
+        }
+      }
+      // Processes data. Syntax is run <number of loops> <increments>. The
+      // number loops specifies the number of increments the program will run.
+      // After each increment, the data stored currently in the program is
+      // exported and re-read back into the program. This is to ensure that the
+      // program can be terminated without losing a large quantity of data. The
+      // increment is the number of families read per 'save'.
+      if (command.indexOf("run") > -1 && !(command.indexOf("ToEnd") > -1))
+      {
+        try
+        {
+
+        inputScanner.next();
+
+        int loops = inputScanner.nextInt();
+        int increments = inputScanner.nextInt();
+        boolean keepRaw = inputScanner.nextBoolean();
+
+        for (int i = 0; i < loops; i++)
+        {
+          analyser.run(increments, keepRaw);
+          System.out.println("Saved");
+        }
+        System.out.println("Task completed");
+        continue;
+        } catch (Exception e)
+        {
+          System.out.println("Command failed");
+        }
+        continue;
+      }
+      if ((command.indexOf("runToEnd") > -1))
+      {
+        try
+        {
+
+          inputScanner.next();
+          int minCount = inputScanner.nextInt();
+          int maxCount = inputScanner.nextInt();
+          boolean keepRaw = inputScanner.nextBoolean();
+          boolean forClans = inputScanner.nextBoolean();
+          analyser.runToEnd(minCount, maxCount, keepRaw, forClans);
+          System.out.println("Task completed");
+        } catch (Exception e)
+        {
+          System.out.println("Command failed");
+        }
+        continue;
+      }
+      // terminates program. Syntax is terminate.
+      if (command.indexOf("terminate") > -1)
+      {
+        running = false;
+        continue;
+      }
+      // clears files in current directory (Only a specific set of files).
+      // Syntax is clear.
+      if (command.indexOf("clear") > -1)
+      {
+        analyser.clear();
+        continue;
+      }
+      // changes current directory. Syntax is cd <directory>
+      if (command.indexOf("cd") > -1)
+      {
+        try
+        {
+        inputScanner.next();
+        analyser.setFolder(inputScanner.next());
+        } catch (Exception e)
+        {
+          System.out.println("Command failed");
+
+        }
+        continue;
+      }
+
+      if (command.indexOf("getFamName") > -1)
+      {
+        try
+        {
+        inputScanner.next();
+        System.out.println(analyser.getFamilyName(inputScanner.nextInt()));
+
+        } catch (Exception e)
+        {
+          System.out.println("Command failed");
+        }
+        continue;
+      }
+      if (command.indexOf("sortIntoClans") > -1)
+      {
+        inputScanner.next();
+        analyser.sortIntoClans(inputScanner.next());
+          continue;
+
+      }
+      if (command.indexOf("setFamilies") > -1)
+      {
+        inputScanner.next();
+        analyser.setFamilies(inputScanner.next());
+        continue;
+
+      }
+
+      if (command.indexOf("setHMMs") > -1)
+      {
+        inputScanner.next();
+        analyser.setHmms(inputScanner.next());
+        continue;
+
+      }
+
+      if (command.indexOf("alignWithinClans") > -1)
+      {
+        inputScanner.next();
+        String export = inputScanner.next();
+        String clans = inputScanner.next();
+        analyser.alignWithinClan(export, clans);
+        continue;
+
+      }
+
+      System.out.println("Unrecognised command");
+    }
+
+
+
+
+  }
+
+}
index 1366ada..18c2aed 100644 (file)
@@ -57,6 +57,7 @@ import jalview.viewmodel.styles.ViewStyle;
 import jalview.workers.AlignCalcManager;
 import jalview.workers.ComplementConsensusThread;
 import jalview.workers.ConsensusThread;
+import jalview.workers.InformationThread;
 import jalview.workers.StrucConsensusThread;
 
 import java.awt.Color;
@@ -97,10 +98,69 @@ public abstract class AlignmentViewport
 
   protected Deque<CommandI> redoList = new ArrayDeque<>();
 
+  protected String sequenceSetID;
+
+  /*
+   * probably unused indicator that view is of a dataset rather than an
+   * alignment
+   */
+  protected boolean isDataset = false;
+
+  private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
+
+  protected ColumnSelection colSel = new ColumnSelection();
+
+  public boolean autoCalculateConsensus = true;
+
+  protected boolean autoCalculateStrucConsensus = true;
+
+  protected boolean ignoreGapsInConsensusCalculation = false;
+
+  protected boolean ignoreBelowBackGroundFrequencyCalculation = false;
+
+  protected boolean infoLetterHeight = false;
+
+  protected ResidueShaderI residueShading = new ResidueShader();
+
+  protected AlignmentAnnotation consensus;
+
+  protected AlignmentAnnotation complementConsensus;
+
+  protected AlignmentAnnotation occupancy;
+
+  protected AlignmentAnnotation strucConsensus;
+
+  protected AlignmentAnnotation conservation;
+
+  protected AlignmentAnnotation quality;
+
+  /**
+   * alignment displayed in the viewport
+   */
+  private AlignmentI alignment;
+
+  /**
+   * results of alignment consensus analysis for visible portion of view
+   */
+  protected ProfilesI consensusProfiles;
+
+  /**
+   * HMM profile for the alignment
+   */
+  protected ProfilesI hmmProfiles;
+
+  /**
+   * results of cDNA complement consensus visible portion of view
+   */
+  protected Hashtable[] hcomplementConsensus;
+
   /**
-   * alignment displayed in the viewport. Please use get/setter
+   * results of secondary structure base pair consensus for visible portion of
+   * view
    */
-  protected AlignmentI alignment;
+  protected Hashtable[] hStrucConsensus;
+
+  protected Conservation hconservation;
 
   public AlignmentViewport(AlignmentI al)
   {
@@ -581,14 +641,6 @@ public abstract class AlignmentViewport
     return alignment.getGapCharacter();
   }
 
-  protected String sequenceSetID;
-
-  /**
-   * probably unused indicator that view is of a dataset rather than an
-   * alignment
-   */
-  protected boolean isDataset = false;
-
   public void setDataset(boolean b)
   {
     isDataset = b;
@@ -599,18 +651,6 @@ public abstract class AlignmentViewport
     return isDataset;
   }
 
-  private Map<SequenceI, SequenceCollectionI> hiddenRepSequences;
-
-  protected ColumnSelection colSel = new ColumnSelection();
-
-  public boolean autoCalculateConsensus = true;
-
-  protected boolean autoCalculateStrucConsensus = true;
-
-  protected boolean ignoreGapsInConsensusCalculation = false;
-
-  protected ResidueShaderI residueShading = new ResidueShader();
-
   @Override
   public void setGlobalColourScheme(ColourSchemeI cs)
   {
@@ -683,41 +723,6 @@ public abstract class AlignmentViewport
   {
     return residueShading;
   }
-
-  protected AlignmentAnnotation consensus;
-
-  protected AlignmentAnnotation complementConsensus;
-
-  protected AlignmentAnnotation gapcounts;
-
-  protected AlignmentAnnotation strucConsensus;
-
-  protected AlignmentAnnotation conservation;
-
-  protected AlignmentAnnotation quality;
-
-  protected AlignmentAnnotation[] groupConsensus;
-
-  protected AlignmentAnnotation[] groupConservation;
-
-  /**
-   * results of alignment consensus analysis for visible portion of view
-   */
-  protected ProfilesI hconsensus = null;
-
-  /**
-   * results of cDNA complement consensus visible portion of view
-   */
-  protected Hashtable[] hcomplementConsensus = null;
-
-  /**
-   * results of secondary structure base pair consensus for visible portion of
-   * view
-   */
-  protected Hashtable[] hStrucConsensus = null;
-
-  protected Conservation hconservation = null;
-
   @Override
   public void setConservation(Conservation cons)
   {
@@ -737,9 +742,9 @@ public abstract class AlignmentViewport
   }
 
   @Override
-  public void setSequenceConsensusHash(ProfilesI hconsensus)
+  public void setConsensusProfiles(ProfilesI hconsensus)
   {
-    this.hconsensus = hconsensus;
+    this.consensusProfiles = hconsensus;
   }
 
   @Override
@@ -749,9 +754,21 @@ public abstract class AlignmentViewport
   }
 
   @Override
-  public ProfilesI getSequenceConsensusHash()
+  public ProfilesI getConsensusProfiles()
+  {
+    return consensusProfiles;
+  }
+
+  @Override
+  public void setHmmProfiles(ProfilesI info)
+  {
+    hmmProfiles = info;
+  }
+
+  @Override
+  public ProfilesI getHmmProfiles()
   {
-    return hconsensus;
+    return hmmProfiles;
   }
 
   @Override
@@ -792,9 +809,9 @@ public abstract class AlignmentViewport
   }
 
   @Override
-  public AlignmentAnnotation getAlignmentGapAnnotation()
+  public AlignmentAnnotation getOccupancyAnnotation()
   {
-    return gapcounts;
+    return occupancy;
   }
 
   @Override
@@ -883,6 +900,16 @@ public abstract class AlignmentViewport
     }
   }
 
+  @Override
+  public void initInformationWorker(final AlignmentViewPanel ap)
+  {
+    if (calculator
+            .getRegisteredWorkersOfClass(InformationThread.class) == null)
+    {
+      calculator.registerWorker(new InformationThread(this, ap));
+    }
+  }
+
   // --------START Structure Conservation
   public void updateStrucConsensus(final AlignmentViewPanel ap)
   {
@@ -946,12 +973,10 @@ public abstract class AlignmentViewport
     strucConsensus = null;
     conservation = null;
     quality = null;
-    groupConsensus = null;
-    groupConservation = null;
-    hconsensus = null;
+    consensusProfiles = null;
     hconservation = null;
     hcomplementConsensus = null;
-    gapcounts = null;
+    occupancy = null;
     calculator = null;
     residueShading = null; // may hold a reference to Consensus
     changeSupport = null;
@@ -1001,6 +1026,21 @@ public abstract class AlignmentViewport
   protected boolean showConsensusHistogram = true;
 
   /**
+   * should hmm profile be rendered by default
+   */
+  protected boolean hmmShowSequenceLogo = false;
+
+  /**
+   * should hmm profile be rendered normalised to row height
+   */
+  protected boolean hmmNormaliseSequenceLogo = false;
+
+  /**
+   * should information histograms be rendered by default
+   */
+  protected boolean hmmShowHistogram = true;
+
+  /**
    * @return the showConsensusProfile
    */
   @Override
@@ -1010,6 +1050,15 @@ public abstract class AlignmentViewport
   }
 
   /**
+   * @return the showInformationProfile
+   */
+  @Override
+  public boolean isShowHMMSequenceLogo()
+  {
+    return hmmShowSequenceLogo;
+  }
+
+  /**
    * @param showSequenceLogo
    *          the new value
    */
@@ -1027,6 +1076,18 @@ public abstract class AlignmentViewport
     this.showSequenceLogo = showSequenceLogo;
   }
 
+  public void setShowHMMSequenceLogo(boolean showHMMSequenceLogo)
+  {
+    if (showHMMSequenceLogo != this.hmmShowSequenceLogo)
+    {
+      this.hmmShowSequenceLogo = showHMMSequenceLogo;
+      // TODO: updateAnnotation if description (tooltip) will show
+      // profile in place of information content?
+      // calculator.updateAnnotationFor(InformationThread.class);
+    }
+    this.hmmShowSequenceLogo = showHMMSequenceLogo;
+  }
+
   /**
    * @param showConsensusHistogram
    *          the showConsensusHistogram to set
@@ -1037,6 +1098,14 @@ public abstract class AlignmentViewport
   }
 
   /**
+   * @param showInformationHistogram
+   */
+  public void setShowInformationHistogram(boolean showInformationHistogram)
+  {
+    this.hmmShowHistogram = showInformationHistogram;
+  }
+
+  /**
    * @return the showGroupConservation
    */
   public boolean isShowGroupConservation()
@@ -1082,6 +1151,17 @@ public abstract class AlignmentViewport
   }
 
   /**
+   * 
+   * @return flag to indicate if the information content histogram should be
+   *         rendered by default
+   */
+  @Override
+  public boolean isShowInformationHistogram()
+  {
+    return this.hmmShowHistogram;
+  }
+
+  /**
    * when set, updateAlignment will always ensure sequences are of equal length
    */
   private boolean padGaps = false;
@@ -1230,14 +1310,22 @@ public abstract class AlignmentViewport
     ignoreGapsInConsensusCalculation = b;
     if (ap != null)
     {
-      updateConsensus(ap);
       if (residueShading != null)
       {
         residueShading.setThreshold(residueShading.getThreshold(),
                 ignoreGapsInConsensusCalculation);
       }
     }
+  }
+
+  public void setIgnoreBelowBackground(boolean b, AlignmentViewPanel ap)
+  {
+    ignoreBelowBackGroundFrequencyCalculation = b;
+  }
 
+  public void setInfoLetterHeight(boolean b, AlignmentViewPanel ap)
+  {
+    infoLetterHeight = b;
   }
 
   private long sgrouphash = -1, colselhash = -1;
@@ -1294,6 +1382,18 @@ public abstract class AlignmentViewport
     return ignoreGapsInConsensusCalculation;
   }
 
+  @Override
+  public boolean isIgnoreBelowBackground()
+  {
+    return ignoreBelowBackGroundFrequencyCalculation;
+  }
+
+  @Override
+  public boolean isInfoLetterHeight()
+  {
+    return infoLetterHeight;
+  }
+
   // property change stuff
   // JBPNote Prolly only need this in the applet version.
   private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
@@ -1853,18 +1953,6 @@ public abstract class AlignmentViewport
     {
       alignment.padGaps();
     }
-    if (autoCalculateConsensus)
-    {
-      updateConsensus(ap);
-    }
-    if (hconsensus != null && autoCalculateConsensus)
-    {
-      updateConservation(ap);
-    }
-    if (autoCalculateStrucConsensus)
-    {
-      updateStrucConsensus(ap);
-    }
 
     // Reset endRes of groups if beyond alignment width
     int alWidth = alignment.getWidth();
@@ -1887,7 +1975,6 @@ public abstract class AlignmentViewport
 
     updateAllColourSchemes();
     calculator.restartWorkers();
-    // alignment.adjustSequenceAnnotations();
   }
 
   /**
@@ -1900,7 +1987,7 @@ public abstract class AlignmentViewport
     {
       rs.alignmentChanged(alignment, hiddenRepSequences);
 
-      rs.setConsensus(hconsensus);
+      rs.setConsensus(consensusProfiles);
       if (rs.conservationApplied())
       {
         rs.setConservation(Conservation.calculateConservation("All",
@@ -1925,7 +2012,7 @@ public abstract class AlignmentViewport
     // depending on if the user wants to see the annotation or not in a
     // specific alignment
 
-    if (hconsensus == null && !isDataset)
+    if (consensusProfiles == null && !isDataset)
     {
       if (!alignment.isNucleotide())
       {
@@ -1940,7 +2027,8 @@ public abstract class AlignmentViewport
               MessageManager.getString("label.consensus_descr"),
               new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
       initConsensus(consensus);
-      initGapCounts();
+
+      initOccupancy();
 
       initComplementConsensus();
     }
@@ -1999,20 +2087,20 @@ public abstract class AlignmentViewport
 
   // these should be extracted from the view model - style and settings for
   // derived annotation
-  private void initGapCounts()
+  private void initOccupancy()
   {
     if (showOccupancy)
     {
-      gapcounts = new AlignmentAnnotation("Occupancy",
+      occupancy = new AlignmentAnnotation("Occupancy",
               MessageManager.getString("label.occupancy_descr"),
               new Annotation[1], 0f, alignment.getHeight(),
               AlignmentAnnotation.BAR_GRAPH);
-      gapcounts.hasText = true;
-      gapcounts.autoCalculated = true;
-      gapcounts.scaleColLabel = true;
-      gapcounts.graph = AlignmentAnnotation.BAR_GRAPH;
+      occupancy.hasText = true;
+      occupancy.autoCalculated = true;
+      occupancy.scaleColLabel = true;
+      occupancy.graph = AlignmentAnnotation.BAR_GRAPH;
 
-      alignment.addAnnotation(gapcounts);
+      alignment.addAnnotation(occupancy);
     }
   }
 
@@ -2146,6 +2234,9 @@ public abstract class AlignmentViewport
     boolean showprf = isShowSequenceLogo();
     boolean showConsHist = isShowConsensusHistogram();
     boolean normLogo = isNormaliseSequenceLogo();
+    boolean showHMMPrf = isShowHMMSequenceLogo();
+    boolean showInfoHist = isShowInformationHistogram();
+    boolean normHMMLogo = isNormaliseHMMSequenceLogo();
 
     /**
      * TODO reorder the annotation rows according to group/sequence ordering on
@@ -2183,6 +2274,9 @@ public abstract class AlignmentViewport
           sg.setshowSequenceLogo(showprf);
           sg.setShowConsensusHistogram(showConsHist);
           sg.setNormaliseSequenceLogo(normLogo);
+          sg.setShowHMMSequenceLogo(showHMMPrf);
+          sg.setShowInformationHistogram(showInfoHist);
+          sg.setNormaliseHMMSequenceLogo(normHMMLogo);
         }
         if (conv)
         {
@@ -2943,6 +3037,19 @@ public abstract class AlignmentViewport
     return sq;
   }
 
+  public boolean hasReferenceAnnotation()
+  {
+    AlignmentAnnotation[] annots = this.alignment.getAlignmentAnnotation();
+    for (AlignmentAnnotation annot : annots)
+    {
+      if ("RF".equals(annot.label) || annot.label.contains("Reference"))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
   @Override
   public void setCurrentTree(TreeModel tree)
   {
@@ -2954,4 +3061,26 @@ public abstract class AlignmentViewport
   {
     return currentTree;
   }
+
+  @Override
+  public boolean isNormaliseSequenceLogo()
+  {
+    return normaliseSequenceLogo;
+  }
+
+  public void setNormaliseSequenceLogo(boolean state)
+  {
+    normaliseSequenceLogo = state;
+  }
+
+  @Override
+  public boolean isNormaliseHMMSequenceLogo()
+  {
+    return hmmNormaliseSequenceLogo;
+  }
+
+  public void setNormaliseHMMSequenceLogo(boolean state)
+  {
+    hmmNormaliseSequenceLogo = state;
+  }
 }
index 08ef3a2..6f0deab 100644 (file)
@@ -74,7 +74,7 @@ public class AlignCalcManager implements AlignCalcManagerI
             .synchronizedList(new ArrayList<AlignCalcWorkerI>());
     updating = Collections.synchronizedMap(
             new Hashtable<Class<? extends AlignCalcWorkerI>, List<AlignCalcWorkerI>>());
-    canUpdate = new HashSet<AlignCalcWorkerI>();
+    canUpdate = new HashSet<>();
   }
 
   @Override
@@ -285,7 +285,7 @@ public class AlignCalcManager implements AlignCalcManagerI
   public List<AlignCalcWorkerI> getRegisteredWorkersOfClass(
           Class<? extends AlignCalcWorkerI> workerClass)
   {
-    List<AlignCalcWorkerI> workingClass = new ArrayList<AlignCalcWorkerI>();
+    List<AlignCalcWorkerI> workingClass = new ArrayList<>();
     synchronized (canUpdate)
     {
       for (AlignCalcWorkerI worker : canUpdate)
@@ -312,8 +312,8 @@ public class AlignCalcManager implements AlignCalcManagerI
   public void removeRegisteredWorkersOfClass(
           Class<? extends AlignCalcWorkerI> typeToRemove)
   {
-    List<AlignCalcWorkerI> removable = new ArrayList<AlignCalcWorkerI>();
-    Set<AlignCalcWorkerI> toremovannot = new HashSet<AlignCalcWorkerI>();
+    List<AlignCalcWorkerI> removable = new ArrayList<>();
+    Set<AlignCalcWorkerI> toremovannot = new HashSet<>();
     synchronized (restartable)
     {
       for (AlignCalcWorkerI worker : restartable)
@@ -363,7 +363,7 @@ public class AlignCalcManager implements AlignCalcManagerI
      * first just find those to remove (to avoid
      * ConcurrentModificationException)
      */
-    List<AlignCalcWorkerI> toRemove = new ArrayList<AlignCalcWorkerI>();
+    List<AlignCalcWorkerI> toRemove = new ArrayList<>();
     for (AlignCalcWorkerI worker : restartable)
     {
       if (worker.involves(ann))
index 335529c..d6a4488 100644 (file)
@@ -50,7 +50,7 @@ public class ConsensusThread extends AlignCalcWorker
     try
     {
       AlignmentAnnotation consensus = getConsensusAnnotation();
-      AlignmentAnnotation gap = getGapAnnotation();
+      AlignmentAnnotation gap = getOccupancyAnnotation();
       if ((consensus == null && gap == null) || calcMan.isPending(this))
       {
         calcMan.workerComplete(this);
@@ -119,7 +119,7 @@ public class ConsensusThread extends AlignCalcWorker
   {
     AlignmentAnnotation consensus = getConsensusAnnotation();
     consensus.annotations = new Annotation[aWidth];
-    AlignmentAnnotation gap = getGapAnnotation();
+    AlignmentAnnotation gap = getOccupancyAnnotation();
     if (gap != null)
     {
       gap.annotations = new Annotation[aWidth];
@@ -137,7 +137,7 @@ public class ConsensusThread extends AlignCalcWorker
     ProfilesI hconsensus = AAFrequency.calculate(aseqs, width, 0, width,
             true);
 
-    alignViewport.setSequenceConsensusHash(hconsensus);
+    alignViewport.setConsensusProfiles(hconsensus);
     setColourSchemeConsensus(hconsensus);
   }
 
@@ -176,9 +176,9 @@ public class ConsensusThread extends AlignCalcWorker
    * 
    * @return
    */
-  protected AlignmentAnnotation getGapAnnotation()
+  protected AlignmentAnnotation getOccupancyAnnotation()
   {
-    return alignViewport.getAlignmentGapAnnotation();
+    return alignViewport.getOccupancyAnnotation();
   }
 
   /**
@@ -199,10 +199,10 @@ public class ConsensusThread extends AlignCalcWorker
             && hconsensus != null)
     {
       deriveConsensus(consensus, hconsensus);
-      AlignmentAnnotation gap = getGapAnnotation();
-      if (gap != null)
+      AlignmentAnnotation occupancy = getOccupancyAnnotation();
+      if (occupancy != null)
       {
-        deriveGap(gap, hconsensus);
+        deriveOccupancy(occupancy, hconsensus);
       }
     }
   }
@@ -219,7 +219,6 @@ public class ConsensusThread extends AlignCalcWorker
   protected void deriveConsensus(AlignmentAnnotation consensusAnnotation,
           ProfilesI hconsensus)
   {
-
     long nseq = getSequences().length;
     AAFrequency.completeConsensus(consensusAnnotation, hconsensus,
             hconsensus.getStartColumn(), hconsensus.getEndColumn() + 1,
@@ -235,11 +234,11 @@ public class ConsensusThread extends AlignCalcWorker
    * @param hconsensus
    *          the computed consensus data
    */
-  protected void deriveGap(AlignmentAnnotation gapAnnotation,
+  protected void deriveOccupancy(AlignmentAnnotation gapAnnotation,
           ProfilesI hconsensus)
   {
     long nseq = getSequences().length;
-    AAFrequency.completeGapAnnot(gapAnnotation, hconsensus,
+    AAFrequency.completeOccupancyAnnot(gapAnnotation, hconsensus,
             hconsensus.getStartColumn(), hconsensus.getEndColumn() + 1,
             nseq);
   }
@@ -252,6 +251,6 @@ public class ConsensusThread extends AlignCalcWorker
   protected Object getViewportConsensus()
   {
     // TODO convert ComplementConsensusThread to use Profile
-    return alignViewport.getSequenceConsensusHash();
+    return alignViewport.getConsensusProfiles();
   }
 }
diff --git a/src/jalview/workers/InformationThread.java b/src/jalview/workers/InformationThread.java
new file mode 100644 (file)
index 0000000..d719189
--- /dev/null
@@ -0,0 +1,320 @@
+package jalview.workers;
+
+import jalview.analysis.AAFrequency;
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.ProfilesI;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.util.MessageManager;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class calculates HMM Information Content annotations, based on any HMM
+ * consensus sequences and their HMM models. HMM consensus sequences may be
+ * present for the whole alignment, or subgroups of it.
+ *
+ */
+public class InformationThread extends AlignCalcWorker
+{
+  public static final String HMM_CALC_ID = "HMM";
+
+  /**
+   * Constructor
+   * 
+   * @param alignViewport
+   * @param alignPanel
+   */
+  public InformationThread(AlignViewportI alignViewport,
+          AlignmentViewPanel alignPanel)
+  {
+    super(alignViewport, alignPanel);
+  }
+
+  /**
+   * Recomputes Information annotations for any HMM consensus sequences (for
+   * alignment and/or groups)
+   */
+  @Override
+  public void run()
+  {
+    if (alignViewport.getAlignment().getHmmSequences().isEmpty())
+    {
+      return;
+    }
+    if (calcMan.isPending(this))
+    {
+      return;
+    }
+    calcMan.notifyStart(this);
+    // long started = System.currentTimeMillis();
+
+    try
+    {
+      if (calcMan.isPending(this))
+      {
+        // another instance of this is waiting to run
+        calcMan.workerComplete(this);
+        return;
+      }
+      while (!calcMan.notifyWorking(this))
+      {
+        // another thread in progress, wait my turn
+        try
+        {
+          if (ap != null)
+          {
+            ap.paintAlignment(false, false);
+          }
+          Thread.sleep(200);
+        } catch (Exception ex)
+        {
+          ex.printStackTrace();
+        }
+      }
+      if (alignViewport.isClosed())
+      {
+        abortAndDestroy();
+        return;
+      }
+
+      AlignmentI alignment = alignViewport.getAlignment();
+      int aWidth = alignment == null ? -1 : alignment.getWidth();
+      if (aWidth < 0)
+      {
+        calcMan.workerComplete(this);
+        return;
+      }
+
+      /*
+       * compute information profiles for any HMM consensus sequences
+       * for the alignment or sub-groups
+       */
+      computeProfiles(alignment);
+
+      /*
+       * construct the corresponding annotations
+       */
+      updateAnnotation();
+
+      if (ap != null)
+      {
+        ap.adjustAnnotationHeight();
+        ap.paintAlignment(true, true);
+      }
+    } catch (OutOfMemoryError error)
+    {
+      calcMan.disableWorker(this);
+      ap.raiseOOMWarning("calculating information", error);
+    } finally
+    {
+      calcMan.workerComplete(this);
+    }
+  }
+
+  /**
+   * Computes HMM profiles for any HMM consensus sequences (for alignment or
+   * subgroups). Any alignment profile computed is stored on the viewport, any
+   * group profile computed is stored on the respective sequence group.
+   * 
+   * @param alignment
+   * @see AlignViewportI#setHmmProfiles(ProfilesI)
+   */
+  protected void computeProfiles(AlignmentI alignment)
+  {
+    int width = alignment.getWidth();
+
+    /*
+     * alignment HMM profile
+     */
+    List<SequenceI> seqs = alignment.getHmmSequences();
+    if (!seqs.isEmpty())
+    {
+      HiddenMarkovModel hmm = seqs.get(0).getHMM();
+      ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
+              0, width, alignViewport.isIgnoreBelowBackground(),
+              alignViewport.isInfoLetterHeight());
+      alignViewport.setHmmProfiles(hmmProfiles);
+    }
+
+    /*
+     * group HMM profiles
+     */
+    List<SequenceGroup> groups = alignment.getGroups();
+    for (SequenceGroup group : groups)
+    {
+      seqs = group.getHmmSequences();
+      if (!seqs.isEmpty())
+      {
+        HiddenMarkovModel hmm = seqs.get(0).getHMM();
+        ProfilesI hmmProfiles = AAFrequency.calculateHMMProfiles(hmm, width,
+                0, width, group.isIgnoreBelowBackground(),
+                group.isUseInfoLetterHeight());
+        group.setHmmProfiles(hmmProfiles);
+      }
+    }
+  }
+
+  /**
+   * gets the sequences on the alignment on the viewport.
+   * 
+   * @return
+   */
+  protected SequenceI[] getSequences()
+  {
+    return alignViewport.getAlignment().getSequencesArray();
+  }
+
+  /**
+   * Get the Gap annotation for the alignment
+   * 
+   * @return
+   */
+  protected AlignmentAnnotation getGapAnnotation()
+  {
+    return alignViewport.getOccupancyAnnotation();
+  }
+
+  /**
+   * Computes Information Content annotation for any HMM consensus sequences
+   * (for alignment or groups), and updates (or adds) the annotation to the
+   * sequence and the alignment
+   */
+  @Override
+  public void updateAnnotation()
+  {
+    AlignmentI alignment = alignViewport.getAlignment();
+
+    float maxInformation = 0f;
+    List<AlignmentAnnotation> infos = new ArrayList<>();
+
+    /*
+     * annotation for alignment HMM consensus if present
+     */
+    List<SequenceI> hmmSeqs = alignment.getHmmSequences();
+    if (!hmmSeqs.isEmpty())
+    {
+      ProfilesI profile = alignViewport.getHmmProfiles();
+      float m = updateInformationAnnotation(hmmSeqs.get(0), profile, null,
+              infos);
+      maxInformation = Math.max(maxInformation, m);
+    }
+
+    /*
+     * annotation for group HMM consensus if present
+     */
+    for (SequenceGroup group : alignment.getGroups())
+    {
+      hmmSeqs = group.getHmmSequences();
+      ProfilesI profiles = group.getHmmProfiles();
+      float m = updateInformationAnnotation(hmmSeqs.get(0), profiles, group,
+              infos);
+      maxInformation = Math.max(maxInformation, m);
+    }
+
+    /*
+     * maxInformation holds the maximum value of information score;
+     * set this as graphMax in all annotations to scale them all the same
+     */
+    for (AlignmentAnnotation ann : infos)
+    {
+      ann.graphMax = maxInformation;
+    }
+  }
+
+  /**
+   * Updates (and first constructs if necessary) an HMM Profile information
+   * content annotation for a sequence. The <code>group</code> argument is null
+   * for the whole alignment annotation, not null for a subgroup annotation. The
+   * updated annotation is added to the <code>infos</code> list. Answers the
+   * maximum information content value of any annotation (for use as a scaling
+   * factor for display).
+   * 
+   * @param seq
+   * @param profile
+   * @param group
+   * @param infos
+   * @return
+   */
+  protected float updateInformationAnnotation(SequenceI seq,
+          ProfilesI profile, SequenceGroup group,
+          List<AlignmentAnnotation> infos)
+  {
+    if (seq == null || profile == null)
+    {
+      return 0f;
+    }
+
+    AlignmentAnnotation ann = findOrCreateAnnotation(seq, group);
+
+    seq.addAlignmentAnnotation(ann);
+    infos.add(ann);
+
+    float max = AAFrequency.completeInformation(ann, profile,
+            profile.getStartColumn(), profile.getEndColumn() + 1);
+
+    return max;
+  }
+
+  /**
+   * A helper method that first searches for the HMM annotation that matches the
+   * group reference (null for the whole alignment annotation). If found, its
+   * sequence reference is updated to the given sequence (the recomputed HMM
+   * consensus sequence). If not found, it is created. This supports both
+   * creating the annotation the first time hmmbuild is run, and updating it if
+   * hmmbuild is re-run.
+   * 
+   * @param seq
+   * @param group
+   * @return
+   */
+  AlignmentAnnotation findOrCreateAnnotation(SequenceI seq,
+          SequenceGroup group)
+  {
+    /*
+     * can't use Alignment.findOrCreateAnnotation here because we 
+     * want to update, rather than match on, the sequence ref
+     */
+    AlignmentAnnotation info = null;
+
+    AlignmentI alignment = alignViewport.getAlignment();
+    AlignmentAnnotation[] anns = alignment.getAlignmentAnnotation();
+    if (anns != null)
+    {
+      for (AlignmentAnnotation ann : anns)
+      {
+        if (HMM_CALC_ID.equals(ann.getCalcId()) && group == ann.groupRef)
+        {
+          info = ann;
+          info.setSequenceRef(seq);
+          info.label = seq.getName(); // in case group name changed!
+          break;
+        }
+      }
+    }
+
+    if (info == null)
+    {
+      int aWidth = alignment.getWidth();
+      String desc = MessageManager
+              .getString("label.information_description");
+      float graphMax = 6.52f; // todo where does this value derive from?
+      info = new AlignmentAnnotation(seq.getName(), desc,
+              new Annotation[aWidth], 0f, graphMax,
+              AlignmentAnnotation.BAR_GRAPH);
+      info.setCalcId(HMM_CALC_ID);
+      info.setSequenceRef(seq);
+      info.groupRef = group;
+      info.hasText = true;
+      alignment.addAnnotation(info);
+    }
+
+    return info;
+  }
+}
index 0f1a25e..7d661a4 100644 (file)
@@ -31,6 +31,7 @@ import jalview.util.MessageManager;
 import jalview.ws.jws2.dm.AAConSettings;
 import jalview.ws.jws2.dm.JabaWsParamSet;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ParamDatastoreI;
 import jalview.ws.params.WsParamSetI;
 import jalview.ws.uimodel.AlignAnalysisUIText;
 
@@ -108,8 +109,12 @@ public abstract class Jws2Client extends jalview.ws.WSClient
       }
       WsJobParameters jobParams = (preset == null && paramset != null
               && paramset.size() > 0)
-                      ? new WsJobParameters(null, sh, null, paramset)
-                      : new WsJobParameters(sh, preset);
+                      ? new WsJobParameters((ParamDatastoreI) null, sh,
+                              (WsParamSetI) null,
+                              paramset)
+                      : new WsJobParameters((ParamDatastoreI) null, sh,
+                              preset,
+                              (List<Argument>) null);
       if (adjustingExisting)
       {
         jobParams.setName(MessageManager
@@ -117,8 +122,9 @@ public abstract class Jws2Client extends jalview.ws.WSClient
       }
       if (!jobParams.showRunDialog())
       {
-        return false;
+        return false; // dialog cancelled
       }
+
       WsParamSetI prset = jobParams.getPreset();
       if (prset == null)
       {
index db6e03f..c4fc66b 100644 (file)
@@ -75,7 +75,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     /**
      * input
      */
-    ArrayList<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
+    ArrayList<compbio.data.sequence.FastaSequence> seqs = new ArrayList<>();
 
     /**
      * output
@@ -139,7 +139,6 @@ class MsaWSThread extends AWS2Thread implements WSClientI
       compbio.data.sequence.FastaSequence seq;
       for (int i = 0, n = 0; i < seqs.length; i++)
       {
-
         String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
         // for
         // any
@@ -379,7 +378,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI
 
     public List<Argument> getJabaArguments()
     {
-      List<Argument> newargs = new ArrayList<Argument>();
+      List<Argument> newargs = new ArrayList<>();
       if (preset != null && preset instanceof JabaWsParamSet)
       {
         newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
@@ -931,7 +930,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI
   void displayResults(boolean newFrame)
   {
     // view input or result data for each block
-    List<AlignmentOrder> alorders = new ArrayList<AlignmentOrder>();
+    List<AlignmentOrder> alorders = new ArrayList<>();
     SequenceI[][] results = new SequenceI[jobs.length][];
     AlignmentOrder[] orders = new AlignmentOrder[jobs.length];
     String lastProgram = null;
@@ -981,7 +980,6 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     if (newFrame)
     {
       displayInNewFrame(al, alorders, hidden);
-
     }
     else
     {
@@ -1077,7 +1075,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     else
     {
       // construct a non-redundant ordering set
-      List<String> names = new ArrayList<String>();
+      List<String> names = new ArrayList<>();
       for (int i = 0, l = alorders.size(); i < l; i++)
       {
         String orderName = " Region " + i;
index da46745..47f454a 100644 (file)
@@ -29,7 +29,7 @@ public interface ValueConstrainI
 
   public enum ValueType
   {
-    Integer, Float, String
+    Integer, Float, String, Double
   };
 
   ValueType getType();
index f80ff77..05abc3a 100644 (file)
  */
 package jalview.ws.params.simple;
 
-import jalview.ws.params.OptionI;
-
 import java.net.URL;
 import java.util.Arrays;
 
-public class BooleanOption extends Option implements OptionI
+public class BooleanOption extends Option
 {
 
   public BooleanOption(String name, String descr, boolean required,
           boolean defVal, boolean val, URL link)
   {
-
-    super(name, descr, required, (defVal ? name : ""), (val ? name : ""),
-            Arrays.asList(new String[]
-            { name }), link);
+    super(name, descr, required, (defVal ? name : null),
+            (val ? name : null),
+            Arrays.asList(name), link);
   }
 
 }
diff --git a/src/jalview/ws/params/simple/DoubleParameter.java b/src/jalview/ws/params/simple/DoubleParameter.java
new file mode 100644 (file)
index 0000000..6b76170
--- /dev/null
@@ -0,0 +1,76 @@
+package jalview.ws.params.simple;
+
+import jalview.ws.params.ParameterI;
+import jalview.ws.params.ValueConstrainI;
+
+/**
+ * 
+ * @author TZVanaalten
+ *
+ */
+public class DoubleParameter extends Option implements ParameterI
+{
+  double defval;
+
+  double min;
+
+  double max;
+
+  @Override
+  public ValueConstrainI getValidValue()
+  {
+    return new ValueConstrainI()
+    {
+      @Override
+      public ValueType getType()
+      {
+        return ValueType.Double;
+      }
+
+      @Override
+      public Number getMin()
+      {
+        return min < max ? min : null;
+      }
+
+      @Override
+      public Number getMax()
+      {
+        return min < max ? max : null;
+      }
+    };
+  }
+
+  public DoubleParameter(DoubleParameter parm)
+  {
+    super(parm);
+    max = parm.max;
+    min = parm.min;
+  }
+
+  public DoubleParameter(String name, String description, boolean required,
+          Double defValue, double min, double max)
+  {
+    super(name, description, required, String.valueOf(defValue), null, null,
+            null);
+    defval = defValue;
+    this.min = min;
+    this.max = max;
+  }
+
+  public DoubleParameter(String name, String description, boolean required,
+          Double defValue, Double value, double min, double max)
+  {
+    super(name, description, required, String.valueOf(defValue),
+            String.valueOf(value), null, null);
+    defval = defValue;
+    this.min = min;
+    this.max = max;
+  }
+
+  @Override
+  public DoubleParameter copy()
+  {
+    return new DoubleParameter(this);
+  }
+}
index fb34e89..b3a01b2 100644 (file)
@@ -31,8 +31,11 @@ public class IntegerParameter extends Option implements ParameterI
 {
   int defval;
 
-  int min, max;
+  int min;
 
+  int max;
+
+  @Override
   public ValueConstrainI getValidValue()
   {
     return new ValueConstrainI()
@@ -47,27 +50,13 @@ public class IntegerParameter extends Option implements ParameterI
       @Override
       public Number getMin()
       {
-        if (min < max)
-        {
-          return min;
-        }
-        else
-        {
-          return null;
-        }
+        return min < max ? min : null;
       }
 
       @Override
       public Number getMax()
       {
-        if (min < max)
-        {
-          return max;
-        }
-        else
-        {
-          return null;
-        }
+        return min < max ? max : null;
       }
     };
   }
diff --git a/src/jalview/ws/params/simple/LogarithmicParameter.java b/src/jalview/ws/params/simple/LogarithmicParameter.java
new file mode 100644 (file)
index 0000000..af80181
--- /dev/null
@@ -0,0 +1,80 @@
+package jalview.ws.params.simple;
+
+import jalview.ws.params.ParameterI;
+import jalview.ws.params.ValueConstrainI;
+
+/**
+ * A model for a numeric-valued parameter which should be displayed using a
+ * logarithmic scale
+ * 
+ * @author TZVanaalten
+ */
+public class LogarithmicParameter extends Option implements ParameterI
+{
+  final double defval;
+
+  final double min;
+
+  final double max;
+
+  @Override
+  public ValueConstrainI getValidValue()
+  {
+    return new ValueConstrainI()
+    {
+
+      @Override
+      public ValueType getType()
+      {
+        return ValueType.Double;
+      }
+
+      @Override
+      public Number getMin()
+      {
+        return min < max ? min : null;
+      }
+
+      @Override
+      public Number getMax()
+      {
+        return min < max ? max : null;
+      }
+    };
+  }
+
+  public LogarithmicParameter(LogarithmicParameter parm)
+  {
+    super(parm);
+    max = parm.max;
+    min = parm.min;
+    defval = 0D;
+  }
+
+  public LogarithmicParameter(String name, String description,
+          boolean required, Double defValue, double min, double max)
+  {
+    super(name, description, required, String.valueOf(defValue), null, null,
+            null);
+    defval = defValue;
+    this.min = min;
+    this.max = max;
+  }
+
+  public LogarithmicParameter(String name, String description,
+          boolean required, Double defValue, double value, double min,
+          double max)
+  {
+    super(name, description, required, String.valueOf(defValue),
+            String.valueOf(value), null, null);
+    defval = defValue;
+    this.min = min;
+    this.max = max;
+  }
+
+  @Override
+  public LogarithmicParameter copy()
+  {
+    return new LogarithmicParameter(this);
+  }
+}
index 653359f..f0126df 100644 (file)
@@ -29,10 +29,21 @@ import java.util.List;
 
 public class Option implements OptionI
 {
+  String name;
 
-  String name, value, defvalue, description;
+  /*
+   * current value in string format, or "null" if undefined
+   */
+  String value;
 
-  ArrayList<String> possibleVals = new ArrayList<String>();
+  /*
+   * default value in string format, or "null" if undefined
+   */
+  String defvalue;
+
+  String description;
+
+  ArrayList<String> possibleVals = new ArrayList<>();
 
   boolean required;
 
@@ -84,11 +95,17 @@ public class Option implements OptionI
   {
     name = new String(opt.name);
     if (opt.value != null)
+    {
       value = new String(opt.value);
+    }
     if (opt.defvalue != null)
+    {
       defvalue = new String(opt.defvalue);
+    }
     if (opt.description != null)
+    {
       description = new String(opt.description);
+    }
     if (opt.possibleVals != null)
     {
       possibleVals = (ArrayList<String>) opt.possibleVals.clone();
@@ -113,7 +130,7 @@ public class Option implements OptionI
     this.defvalue = defValue;
     if (possibleVals != null)
     {
-      this.possibleVals = new ArrayList<String>();
+      this.possibleVals = new ArrayList<>();
       this.possibleVals.addAll(possibleVals);
     }
     this.fdetails = fdetails;
@@ -125,4 +142,13 @@ public class Option implements OptionI
     Option opt = new Option(this);
     return opt;
   }
+
+  /**
+   * toString method to help identify options in the debugger only
+   */
+  @Override
+  public String toString()
+  {
+    return this.getClass().getName() + ":" + name;
+  }
 }
diff --git a/src/jalview/ws/params/simple/Parameter.java b/src/jalview/ws/params/simple/Parameter.java
deleted file mode 100644 (file)
index e2c81a6..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- * 
- * This file is part of Jalview.
- * 
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License 
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *  
- * Jalview is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty 
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
- * PURPOSE.  See the GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-package jalview.ws.params.simple;
-
-import jalview.ws.params.OptionI;
-import jalview.ws.params.ParameterI;
-import jalview.ws.params.ValueConstrainI;
-
-public abstract class Parameter extends Option
-        implements OptionI, ParameterI
-{
-  ValueConstrainI validator;
-
-  @Override
-  public ValueConstrainI getValidValue()
-  {
-    return validator;
-  }
-
-  public Parameter(Parameter parm)
-  {
-    super(parm);
-  }
-
-  public Parameter(ValueConstrainI validator)
-  {
-    super();
-    this.validator = validator;
-  }
-
-  @Override
-  public abstract Parameter copy();
-}
index d613d58..254eb80 100644 (file)
  */
 package jalview.ws.params.simple;
 
+import java.util.List;
+
+/**
+ * A parameter with options intended to be rendered as radio buttons
+ */
 public class StringChoiceParameter extends Option
 {
 
+  /**
+   * Constructor
+   * 
+   * @param name
+   * @param description
+   * @param options
+   * @param def
+   */
+  public StringChoiceParameter(String name, String description,
+          List<String> options, String def)
+  {
+    super(name, description, true, def, def, options, null);
+  }
 }
diff --git a/src/jalview/ws/params/simple/StringParameter.java b/src/jalview/ws/params/simple/StringParameter.java
new file mode 100644 (file)
index 0000000..b61836a
--- /dev/null
@@ -0,0 +1,84 @@
+package jalview.ws.params.simple;
+
+import jalview.ws.params.ParameterI;
+import jalview.ws.params.ValueConstrainI;
+
+import java.util.Collection;
+
+public class StringParameter extends Option implements ParameterI
+{
+  @Override
+  public ValueConstrainI getValidValue()
+  {
+    return new StringValueConstrain();
+  }
+
+  @Override
+  public ParameterI copy()
+  {
+    return new StringParameter(this);
+  }
+
+  private class StringValueConstrain implements ValueConstrainI
+  {
+
+    @Override
+    public ValueType getType()
+    {
+      return ValueType.String;
+    }
+
+    @Override
+    public Number getMax()
+    {
+      return null;
+    }
+
+    @Override
+    public Number getMin()
+    {
+      return null;
+    }
+
+  }
+
+  public StringParameter(StringParameter parm)
+  {
+    this.name = parm.name;
+    this.defvalue = parm.defvalue;
+  }
+
+  public StringParameter(String name, String description, boolean required,
+          String defValue)
+  {
+    super(name, description, required, String.valueOf(defValue), null, null,
+            null);
+    this.defvalue = defValue;
+  }
+
+  public StringParameter(String name, String description, boolean required,
+          String defValue, String value)
+  {
+    super(name, description, required, String.valueOf(defValue),
+            String.valueOf(value), null, null);
+    this.defvalue = defValue;
+  }
+
+  /**
+   * Constructor for a parameter with a list of possible values
+   * 
+   * @param name2
+   * @param description2
+   * @param isrequired
+   * @param defValue
+   * @param value
+   * @param possibleVals
+   */
+  public StringParameter(String name2, String description2,
+          boolean isrequired, String defValue, String value,
+          Collection<String> possibleVals)
+  {
+    super(name2, description2, isrequired, defValue, value, possibleVals,
+            null);
+  }
+}
index 75fb39e..2b6c512 100644 (file)
@@ -25,17 +25,27 @@ import static org.testng.AssertJUnit.assertNull;
 
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.Profile;
 import jalview.datamodel.ProfileI;
+import jalview.datamodel.Profiles;
 import jalview.datamodel.ProfilesI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
+import jalview.io.DataSourceType;
+import jalview.io.FileParse;
+import jalview.io.HMMFile;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 public class AAFrequencyTest
 {
+  HiddenMarkovModel hmm;
 
   @BeforeClass(alwaysRun = true)
   public void setUpJvOptionPane()
@@ -44,6 +54,17 @@ public class AAFrequencyTest
     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
   }
 
+  @BeforeClass(alwaysRun = true)
+  public void setUp() throws IOException, MalformedURLException
+  {
+    /*
+     * load a dna (ACGT) HMM file to a HiddenMarkovModel
+     */
+    HMMFile hmmFile = new HMMFile(new FileParse(
+            "test/jalview/io/test_MADE1_hmm.txt", DataSourceType.FILE));
+    hmm = hmmFile.getHMM();
+  }
+
   @Test(groups = { "Functional" })
   public void testCalculate_noProfile()
   {
@@ -232,4 +253,94 @@ public class AAFrequencyTest
     assertEquals("T 75%", ann.description);
     assertEquals("T", ann.displayCharacter);
   }
+
+  @Test(groups = { "Functional" })
+  public void testExtractHMMProfile()
+          throws MalformedURLException, IOException
+  {
+    int[] expected = { 0, 4, 100, 'T', 71, 'C', 12, 'G', 9, 'A', 9 };
+    int[] actual = AAFrequency.extractHMMProfile(hmm, 17, false, false);
+    for (int i = 0; i < actual.length; i++)
+    {
+      if (i == 2)
+      {
+        assertEquals(actual[i], expected[i]);
+      }
+      else
+      {
+        assertEquals(actual[i], expected[i]);
+      }
+    }
+
+    int[] expected2 = { 0, 4, 100, 'A', 85, 'C', 0, 'G', 0, 'T', 0 };
+    int[] actual2 = AAFrequency.extractHMMProfile(hmm, 2, true, false);
+    for (int i = 0; i < actual2.length; i++)
+    {
+      if (i == 2)
+      {
+        assertEquals(actual[i], expected[i]);
+      }
+      else
+      {
+        assertEquals(actual[i], expected[i]);
+      }
+    }
+
+    assertNull(AAFrequency.extractHMMProfile(null, 98978867, true, false));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetAnalogueCount()
+  {
+    /*
+     * 'T' in column 0 has emission probability 0.7859, scales to 7859
+     */
+    int count = AAFrequency.getAnalogueCount(hmm, 0, 'T', false, false);
+    assertEquals(7859, count);
+
+    /*
+     * same with 'use info height': value is multiplied by log ratio
+     * log(value / background) / log(2) = log(0.7859/0.25)/0.693
+     * = log(3.1)/0.693 = 1.145/0.693 = 1.66
+     * so value becomes 1.2987 and scales up to 12987
+     */
+    count = AAFrequency.getAnalogueCount(hmm, 0, 'T', false, true);
+    assertEquals(12987, count);
+
+    /*
+     * 'G' in column 20 has emission probability 0.75457, scales to 7546
+     */
+    count = AAFrequency.getAnalogueCount(hmm, 20, 'G', false, false);
+    assertEquals(7546, count);
+
+    /*
+     * 'G' in column 1077 has emission probability 0.0533, here
+     * ignored (set to 0) since below background of 0.25
+     */
+    count = AAFrequency.getAnalogueCount(hmm, 1077, 'G', true, false);
+    assertEquals(0, count);
+  }
+
+  @Test(groups = { "Functional" })
+  public void testCompleteInformation()
+  {
+    ProfileI prof1 = new Profile(1, 0, 100, "A");
+    ProfileI prof2 = new Profile(1, 0, 100, "-");
+
+    ProfilesI profs = new Profiles(new ProfileI[] { prof1, prof2 });
+    Annotation ann1 = new Annotation(6.5f);
+    Annotation ann2 = new Annotation(0f);
+    Annotation[] annots = new Annotation[] { ann1, ann2 };
+    SequenceI seq = new Sequence("", "AA", 0, 0);
+    seq.setHMM(hmm);
+    AlignmentAnnotation annot = new AlignmentAnnotation("", "", annots);
+    annot.setSequenceRef(seq);
+    AAFrequency.completeInformation(annot, profs, 0, 1);
+    float ic = annot.annotations[0].value;
+    assertEquals(0.91532f, ic, 0.0001f);
+    ic = annot.annotations[1].value;
+    assertEquals(0f, ic, 0.0001f);
+    int i = 0;
+  }
+
 }
index 16ca70d..a1623f6 100644 (file)
@@ -23,6 +23,7 @@ package jalview.analysis.scoremodels;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 
+import jalview.api.AlignViewportI;
 import jalview.api.analysis.ScoreModelI;
 import jalview.api.analysis.SimilarityParamsI;
 import jalview.datamodel.Alignment;
@@ -32,7 +33,6 @@ import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
-import jalview.gui.AlignViewport;
 import jalview.gui.JvOptionPane;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
@@ -280,7 +280,7 @@ public class FeatureDistanceModelTest
   public void testFindDistances_withParams()
   {
     AlignFrame af = setupAlignmentView();
-    AlignViewport viewport = af.getViewport();
+    AlignViewportI viewport = af.getViewport();
     AlignmentView view = viewport.getAlignmentView(false);
 
     ScoreModelI sm = new FeatureDistanceModel();
index 1d1ebd6..0f6b129 100644 (file)
@@ -1351,7 +1351,7 @@ public class AlignmentTest
             "Temperature Factor", null, false, seq, null);
     assertNotNull(ala);
     assertEquals(seq, ala.sequenceRef);
-    assertEquals("", ala.calcId);
+    assertEquals("", ala.getCalcId());
   }
 
   @Test(groups = "Functional")
index b201c7e..9be344c 100644 (file)
@@ -23,10 +23,10 @@ package jalview.datamodel;
 import static org.testng.Assert.assertEquals;
 
 import jalview.gui.AlignFrame;
-import jalview.gui.AlignViewport;
 import jalview.gui.JvOptionPane;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
+import jalview.viewmodel.AlignmentViewport;
 
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -60,7 +60,7 @@ public class AlignmentViewTest
   {
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             ">s1\n0123456789\n", DataSourceType.PASTE);
-    AlignViewport av = af.getViewport();
+    AlignmentViewport av = af.getViewport();
     AlignmentView view = av.getAlignmentView(true);
 
     /*
diff --git a/test/jalview/datamodel/HMMNodeTest.java b/test/jalview/datamodel/HMMNodeTest.java
new file mode 100644 (file)
index 0000000..f2aef06
--- /dev/null
@@ -0,0 +1,42 @@
+package jalview.datamodel;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.io.DataSourceType;
+import jalview.io.FileParse;
+import jalview.io.HMMFile;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class HMMNodeTest
+{
+  private HiddenMarkovModel hmm;
+
+  @BeforeClass(alwaysRun = true)
+  public void setUp() throws MalformedURLException, IOException
+  {
+    /*
+     * load hmm model of a Kinase domain to a HiddenMarkovModel
+     */
+    HMMFile file = new HMMFile(new FileParse(
+            "test/jalview/io/test_PKinase_hmm.txt", DataSourceType.FILE));
+    hmm = file.getHMM();
+  }
+
+  @Test(groups="Functional")
+  public void testGetMaxMatchEmissionIdex()
+  {
+    assertEquals(hmm.getAlphabetType(), "amino");
+    String symbols = hmm.getSymbols();
+
+    assertEquals(hmm.getNode(1).getMaxMatchEmissionIndex(),
+            symbols.indexOf('Y'));
+
+    assertEquals(hmm.getNode(17).getMaxMatchEmissionIndex(),
+            symbols.indexOf('K'));
+  }
+}
diff --git a/test/jalview/datamodel/HiddenMarkovModelTest.java b/test/jalview/datamodel/HiddenMarkovModelTest.java
new file mode 100644 (file)
index 0000000..7978da2
--- /dev/null
@@ -0,0 +1,146 @@
+package jalview.datamodel;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.io.DataSourceType;
+import jalview.io.FileParse;
+import jalview.io.HMMFile;
+import jalview.schemes.ResidueProperties;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Map;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class HiddenMarkovModelTest {
+
+  HiddenMarkovModel hmm;
+
+  @BeforeClass(alwaysRun = true)
+  public void setUp() throws MalformedURLException, IOException
+  {
+    /*
+     * load hmm model of a Kinase domain to a HiddenMarkovModel
+     */
+    HMMFile file = new HMMFile(new FileParse(
+            "test/jalview/io/test_PKinase_hmm.txt", DataSourceType.FILE));
+    hmm = file.getHMM();
+  }
+
+  @Test(groups = "Functional")
+  public void testGetMatchEmissionProbabilities()
+          throws MalformedURLException, IOException
+  {
+    /*
+     * raw value in file is 3.67403
+     * saved as probability e^-X = 0.05259 
+     */
+    double mep = hmm.getMatchEmissionProbability(0, 'R');
+    assertEquals(mep, 0.02537400637, 0.0001d);
+    assertEquals(mep, Math.pow(Math.E, -3.67403), 0.0001d);
+
+    mep = hmm.getMatchEmissionProbability(19, 'W');
+    assertEquals(mep, 0.00588228492, 0.0001d);
+    assertEquals(mep, Math.pow(Math.E, -5.13581), 0.0001d);
+
+    // column 160 is a gapped region of the model
+    mep = hmm.getMatchEmissionProbability(160, 'G');
+    assertEquals(mep, 0D, 0.0001d);
+
+    mep = hmm.getMatchEmissionProbability(475, 'A');
+    assertEquals(mep, 0.04995163708, 0.0001d);
+    assertEquals(mep, Math.pow(Math.E, -2.99670), 0.0001d);
+  }
+  
+  @Test(groups = "Functional")
+  public void testGetInsertEmissionProbabilities()
+  {
+    double iep = hmm.getInsertEmissionProbability(2, 'A');
+    assertEquals(iep, Math.pow(Math.E, -2.68618), 0.0001d);
+    // symbol is not case-sensitive
+    assertEquals(iep, hmm.getInsertEmissionProbability(2, 'a'));
+
+    iep = hmm.getInsertEmissionProbability(5, 'T');
+    assertEquals(iep, Math.pow(Math.E, -2.77519), 0.0001d);
+
+    // column 161 is gapped in the hmm
+    iep = hmm.getInsertEmissionProbability(161, 'K');
+    assertEquals(iep, 0D, 0.0001d);
+
+    iep = hmm.getInsertEmissionProbability(472, 'L');
+    assertEquals(iep, Math.pow(Math.E, -2.69355), 0.0001d);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetStateTransitionProbabilities()
+  {
+    // * in model file treated as negative infinity
+    double stp = hmm.getStateTransitionProbability(475,
+            HiddenMarkovModel.MATCHTODELETE);
+    assertEquals(stp, Double.NEGATIVE_INFINITY);
+
+    // file value is 5.01631, saved as e^-5.01631
+    stp = hmm.getStateTransitionProbability(8,
+            HiddenMarkovModel.MATCHTOINSERT);
+    assertEquals(stp, Math.pow(Math.E, -5.01631), 0.0001D);
+
+    stp = hmm.getStateTransitionProbability(36,
+            HiddenMarkovModel.MATCHTODELETE);
+    assertEquals(stp, Math.pow(Math.E, -5.73865), 0.0001D);
+
+    stp = hmm.getStateTransitionProbability(22,
+            HiddenMarkovModel.INSERTTOMATCH);
+    assertEquals(stp, Math.pow(Math.E, -0.61958), 0.0001D);
+
+    stp = hmm.getStateTransitionProbability(80,
+            HiddenMarkovModel.INSERTTOINSERT);
+    assertEquals(stp, Math.pow(Math.E, -0.77255), 0.0001D);
+
+    stp = hmm.getStateTransitionProbability(475,
+            HiddenMarkovModel.DELETETOMATCH);
+    assertEquals(stp, 1D, 0.0001D);
+
+    stp = hmm.getStateTransitionProbability(218,
+            HiddenMarkovModel.DELETETODELETE);
+    assertEquals(stp, Math.pow(Math.E, -0.95510), 0.0001D);
+  }
+  
+  @Test(groups = "Functional")
+  public void testGetConsensusSequence()
+  {
+    SequenceI seq = hmm.getConsensusSequence();
+    String subStr = seq.getSequenceAsString().substring(0, 10);
+    assertEquals(subStr, "yelleklGsG");
+    subStr = seq.getSequenceAsString().substring(150, 161);
+    assertEquals(subStr, "-dllk------");
+  }
+
+  /**
+   * A rather pointless test that reproduces the code implemented and asserts
+   * the result is the same...
+   */
+  @Test(groups = "Functional")
+  public void testGetInformationContent()
+  {
+    /*
+     * information measure is sum over all symbols of 
+     * emissionProb * log(emissionProb / background) / log(2)
+     */
+    Map<Character, Float> uniprotFreqs = ResidueProperties.backgroundFrequencies
+            .get("amino");
+    int col = 4;
+    float expected = 0f;
+    for (char aa : hmm.getSymbols().toCharArray())
+    {
+      double mep = hmm.getMatchEmissionProbability(col, aa);
+      float background = uniprotFreqs.get(aa);
+      expected += mep * Math.log(mep / background);
+    }
+    expected /= Math.log(2D);
+
+    float actual = hmm.getInformationContent(col);
+    assertEquals(actual, expected, 0.0001d);
+  }
+}
index 11b993d..efd71e6 100644 (file)
@@ -31,6 +31,7 @@ import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
 
 import jalview.gui.AlignViewport;
 import jalview.gui.JvOptionPane;
+import jalview.viewmodel.AlignmentViewport;
 
 import java.util.List;
 
@@ -487,7 +488,7 @@ public class HiddenSequencesTest
      * represent seqs 2-4 with seq3
      * this hides seq2 and seq4 but not seq3
      */
-    AlignViewport av = new AlignViewport(al);
+    AlignmentViewport av = new AlignViewport(al);
     SequenceGroup sg = new SequenceGroup();
     sg.addSequence(seqs[1], false);
     sg.addSequence(seqs[2], false);
index 4eb6dbf..9a8f93d 100644 (file)
@@ -27,6 +27,8 @@ import static org.testng.Assert.assertTrue;
 import jalview.datamodel.ResidueCount.SymbolCounts;
 import jalview.gui.JvOptionPane;
 
+import java.util.Arrays;
+
 import org.junit.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
@@ -69,6 +71,7 @@ public class ResidueCountTest
     assertEquals(rc.getCount('N'), 1);
     assertEquals(rc.getCount('?'), 0);
     assertEquals(rc.getCount('-'), 0);
+    assertEquals(rc.getTotalResidueCount(), 11);
 
     assertFalse(rc.isCountingInts());
     assertFalse(rc.isUsingOtherData());
@@ -90,6 +93,7 @@ public class ResidueCountTest
     assertEquals(rc.getCount(' '), 4);
     assertEquals(rc.getCount('-'), 4);
     assertEquals(rc.getCount('.'), 4);
+    assertEquals(rc.getTotalResidueCount(), 0);
     assertFalse(rc.isUsingOtherData());
     assertFalse(rc.isCountingInts());
   }
@@ -158,6 +162,7 @@ public class ResidueCountTest
     assertEquals(rc.getCount('m'), 13);
     assertEquals(rc.getCount('G'), 0);
     assertEquals(rc.getCount('-'), 0);
+    assertEquals(rc.getTotalResidueCount(), 27);
 
     assertFalse(rc.isCountingInts());
     assertFalse(rc.isUsingOtherData());
@@ -439,4 +444,23 @@ public class ResidueCountTest
     assertEquals(rc.getCount('?'), 6);
     assertEquals(rc.getCount('!'), 7);
   }
+
+  @Test(groups = "Functional")
+  public void testConstructor_forSequences()
+  {
+    SequenceI seq1 = new Sequence("seq1", "abcde--. FCD");
+    SequenceI seq2 = new Sequence("seq2", "ab.kKqBd-.");
+    ResidueCount rc = new ResidueCount(Arrays.asList(seq1, seq2));
+
+    assertEquals(rc.getGapCount(), 7);
+    assertEquals(rc.getTotalResidueCount(), 15); // excludes gaps
+    assertEquals(rc.getCount('a'), 2);
+    assertEquals(rc.getCount('A'), 2);
+    assertEquals(rc.getCount('B'), 3);
+    assertEquals(rc.getCount('c'), 2);
+    assertEquals(rc.getCount('D'), 3);
+    assertEquals(rc.getCount('f'), 1);
+    assertEquals(rc.getCount('K'), 2);
+    assertEquals(rc.getCount('Q'), 1);
+  }
 }
index b0af5c8..df88268 100644 (file)
@@ -16,10 +16,10 @@ import jalview.schemes.PIDColourScheme;
 import java.awt.Color;
 import java.util.Collections;
 
-import junit.extensions.PA;
-
 import org.testng.annotations.Test;
 
+import junit.extensions.PA;
+
 public class SequenceGroupTest
 {
   @Test(groups={"Functional"})
@@ -242,7 +242,7 @@ public class SequenceGroupTest
     sg.setDisplayBoxes(false);
     sg.setDisplayText(false);
     sg.setColourText(true);
-    sg.isDefined = true;
+    PA.setValue(sg, "isDefined", true);
     sg.setShowNonconserved(true);
     sg.setOutlineColour(Color.red);
     sg.setIdColour(Color.blue);
@@ -275,7 +275,7 @@ public class SequenceGroupTest
     assertEquals(sg2.thresholdTextColour, sg.thresholdTextColour);
     assertEquals(sg2.textColour, sg.textColour);
     assertEquals(sg2.textColour2, sg.textColour2);
-    assertEquals(sg2.getIgnoreGapsConsensus(), sg.getIgnoreGapsConsensus());
+    assertEquals(sg2.isIgnoreGapsConsensus(), sg.isIgnoreGapsConsensus());
     assertEquals(sg2.isShowSequenceLogo(), sg.isShowSequenceLogo());
     assertEquals(sg2.isNormaliseSequenceLogo(),
             sg.isNormaliseSequenceLogo());
index b0aaab9..0f15ce4 100644 (file)
@@ -26,6 +26,7 @@ import static org.testng.Assert.assertNotSame;
 import static org.testng.Assert.assertSame;
 import static org.testng.Assert.assertTrue;
 
+import jalview.api.AlignViewportI;
 import jalview.api.FeatureColourI;
 import jalview.bin.Cache;
 import jalview.bin.Jalview;
@@ -47,6 +48,7 @@ import jalview.schemes.JalviewColourScheme;
 import jalview.schemes.StrandColourScheme;
 import jalview.schemes.TurnColourScheme;
 import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.Color;
 import java.util.Iterator;
@@ -208,7 +210,7 @@ public class AlignFrameTest
   @Test(groups = "Functional")
   public void testChangeColour_background_groupsAndThresholds()
   {
-    AlignViewport av = af.getViewport();
+    AlignViewportI av = af.getViewport();
     AlignmentI al = av.getAlignment();
 
     /*
@@ -339,7 +341,7 @@ public class AlignFrameTest
   @Test(groups = "Functional")
   public void testColourThresholdActions()
   {
-    AlignViewport av = af.getViewport();
+    AlignViewportI av = af.getViewport();
     AlignmentI al = av.getAlignment();
 
     /*
@@ -508,7 +510,7 @@ public class AlignFrameTest
   @Test(groups = "Functional")
   public void testNewView_colourThresholds()
   {
-    AlignViewport av = af.getViewport();
+    AlignViewportI av = af.getViewport();
     AlignmentI al = av.getAlignment();
 
     /*
@@ -572,7 +574,7 @@ public class AlignFrameTest
      */
     af.newView_actionPerformed(null);
     assertEquals(af.alignPanel.getViewName(), "View 1");
-    AlignViewport av2 = af.getViewport();
+    AlignmentViewport av2 = af.getViewport();
     assertNotSame(av, av2);
     assertSame(av2, af.alignPanel.av);
     rs = av2.getResidueShading();
index 5ed0cac..6ab2622 100644 (file)
@@ -26,6 +26,7 @@ import static org.testng.AssertJUnit.assertNotNull;
 import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
 
+import jalview.api.AlignViewportI;
 import jalview.bin.Cache;
 import jalview.bin.Jalview;
 import jalview.datamodel.AlignedCodonFrame;
@@ -33,8 +34,6 @@ import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
-import jalview.datamodel.PDBEntry;
-import jalview.datamodel.PDBEntry.Type;
 import jalview.datamodel.SearchResults;
 import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
@@ -46,6 +45,7 @@ import jalview.schemes.ColourSchemeI;
 import jalview.schemes.PIDColourScheme;
 import jalview.structure.StructureSelectionManager;
 import jalview.util.MapList;
+import jalview.viewmodel.AlignmentViewport;
 import jalview.viewmodel.ViewportRanges;
 
 import java.util.ArrayList;
@@ -68,7 +68,7 @@ public class AlignViewportTest
 
   AlignmentI al;
 
-  AlignViewport testee;
+  AlignmentViewport testee;
 
   @BeforeClass(alwaysRun = true)
   public static void setUpBeforeClass() throws Exception
@@ -355,7 +355,7 @@ public class AlignViewportTest
   {
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/uniref50.fa", DataSourceType.FILE);
-    AlignViewport av = af.getViewport();
+    AlignViewportI av = af.getViewport();
     SequenceGroup sg1 = new SequenceGroup();
     SequenceGroup sg2 = new SequenceGroup();
     SequenceGroup sg3 = new SequenceGroup();
@@ -384,8 +384,8 @@ public class AlignViewportTest
     jalview.bin.Cache.setProperty("SHOW_OCCUPANCY", Boolean.FALSE.toString());
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/uniref50.fa", DataSourceType.FILE);
-    AlignViewport av = af.getViewport();
-    Assert.assertNull(av.getAlignmentGapAnnotation(), "Preference did not disable occupancy row.");
+    AlignViewportI av = af.getViewport();
+    Assert.assertNull(av.getOccupancyAnnotation(), "Preference did not disable occupancy row.");
     int c = 0;
     for (AlignmentAnnotation aa : av.getAlignment().findAnnotations(null,
             null, "Occupancy"))
@@ -399,10 +399,10 @@ public class AlignViewportTest
     af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/uniref50.fa", DataSourceType.FILE);
     av = af.getViewport();
-    Assert.assertNotNull(av.getAlignmentGapAnnotation(), "Preference did not enable occupancy row.");
+    Assert.assertNotNull(av.getOccupancyAnnotation(), "Preference did not enable occupancy row.");
     c = 0;
     for (AlignmentAnnotation aa : av.getAlignment().findAnnotations(null,
-            null, av.getAlignmentGapAnnotation().label))
+            null, av.getOccupancyAnnotation().label))
     {
       c++;
     }
@@ -423,7 +423,7 @@ public class AlignViewportTest
     String fasta = ">s1\nA-C\n>s2\nA-C\n>s3\nA-D\n>s4\n--D\n";
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(fasta,
             DataSourceType.PASTE);
-    AlignViewport testme = af.getViewport();
+    AlignmentViewport testme = af.getViewport();
     SequenceI cons = testme.getConsensusSeq();
     assertEquals("A-C", cons.getSequenceAsString());
   }
index 3322ee8..1ea0ba1 100644 (file)
@@ -2,17 +2,19 @@ package jalview.gui;
 
 import static org.testng.Assert.assertEquals;
 
+import jalview.api.AlignViewportI;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.SequenceGroup;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
+import jalview.viewmodel.AlignmentViewport;
 
 import javax.swing.JTextArea;
 
-import junit.extensions.PA;
-
 import org.testng.annotations.Test;
 
+import junit.extensions.PA;
+
 public class PairwiseAlignmentPanelTest
 {
   @Test(groups = "Functional")
@@ -20,7 +22,7 @@ public class PairwiseAlignmentPanelTest
   {
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/uniref50.fa", DataSourceType.FILE);
-    AlignViewport viewport = af.getViewport();
+    AlignViewportI viewport = af.getViewport();
     AlignmentI al = viewport.getAlignment();
 
     /*
@@ -58,7 +60,7 @@ public class PairwiseAlignmentPanelTest
     String seqs = ">Q93XJ9_SOLTU/23-29\nL-KAISNV\n>FER1_PEA/26-32\nV-TTTKAF\n";
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqs,
             DataSourceType.PASTE);
-    AlignViewport viewport = af.getViewport();
+    AlignViewportI viewport = af.getViewport();
 
     PairwiseAlignPanel testee = new PairwiseAlignPanel(viewport);
 
index 359377a..d3d6476 100644 (file)
@@ -22,6 +22,7 @@ package jalview.gui;
 
 import static org.testng.Assert.assertEquals;
 
+import jalview.api.AlignViewportI;
 import jalview.bin.Jalview;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
@@ -41,7 +42,7 @@ import org.testng.annotations.Test;
 public class SequenceRendererTest
 {
   AlignmentI al;
-  AlignViewport av;
+  AlignViewportI av;
 
   SequenceI seq1;
 
diff --git a/test/jalview/hmmer/HMMERTest.java b/test/jalview/hmmer/HMMERTest.java
new file mode 100644 (file)
index 0000000..e3b7067
--- /dev/null
@@ -0,0 +1,134 @@
+package jalview.hmmer;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
+import jalview.io.HMMFile;
+import jalview.util.MessageManager;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.simple.Option;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class HMMERTest {
+
+  AlignFrame frame;
+
+  @BeforeClass(alwaysRun = true)
+  public void setUpBeforeClass() throws Exception
+  {
+    /*
+     * NB: check HMMER_PATH in testProps.jvprops is valid for
+     * the machine on which this runs
+     */
+    Jalview.main(
+            new String[]
+    { "-noquestionnaire", "-nonews", "-props",
+                "test/jalview/hmmer/testProps.jvprops", "-open",
+                "examples/uniref50.fa" });
+    frame = Desktop.getAlignFrames()[0];
+  }
+
+  @AfterClass(alwaysRun = true)
+  public static void tearDownAfterClass() throws Exception
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+  }
+
+  /**
+   * Test with a dependency on locally installed hmmbuild binaries
+   * 
+   * @throws MalformedURLException
+   * @throws IOException
+   */
+  @Test(groups = "External")
+  public void testHMMBuildThenHMMAlign()
+          throws MalformedURLException, IOException
+  {
+    /*
+     * run hmmbuild
+     */
+    testHMMBuild();
+    List<SequenceI> hmms = frame.getViewport().getAlignment()
+            .getHmmSequences();
+    assertFalse(hmms.isEmpty());
+
+    /*
+     * now run hmmalign - by default with respect to the added HMM profile
+     */
+    testHMMAlign();
+  }
+
+  public void testHMMBuild()
+  {
+    /*
+     * set up argument to run hmmbuild for the alignment
+     */
+    ArrayList<ArgumentI> params = new ArrayList<>();
+    String argName = MessageManager.getString("label.hmmbuild_for");
+    String argValue = MessageManager.getString("label.alignment");
+    params.add(
+            new Option(argName, null, false, null, argValue, null, null));
+
+    HMMBuild builder = new HMMBuild(frame, params);
+    builder.run();
+
+    SequenceI seq = frame.getViewport().getAlignment().getSequenceAt(0);
+    HiddenMarkovModel hmm = seq.getHMM();
+    assertNotNull(hmm);
+
+    assertEquals(hmm.getLength(), 148);
+    assertEquals(hmm.getAlphabetType(), "amino");
+    assertEquals(hmm.getName(), "Alignment_HMM");
+    assertEquals(hmm.getProperty(HMMFile.EFF_NUMBER_OF_SEQUENCES),
+            "0.648193");
+  }
+
+  public void testHMMAlign()
+  {
+    HmmerCommand thread = new HMMAlign(frame,
+            new ArrayList<ArgumentI>());
+    thread.run();
+
+    AlignFrame[] alignFrames = Desktop.getAlignFrames();
+    if (alignFrames == null)
+    {
+      fail("No align frame loaded");
+    }
+
+    /*
+     * now have the original align frame, and another for realigned sequences
+     */
+    assertEquals(alignFrames.length, 2);
+    AlignmentI original = alignFrames[0].getViewport().getAlignment();
+    assertNotNull(original);
+    AlignmentI realigned = alignFrames[1].getViewport().getAlignment();
+    assertNotNull(realigned);
+    assertFalse(original.getHmmSequences().isEmpty());
+    assertFalse(realigned.getHmmSequences().isEmpty());
+
+    SequenceI ferCapan = original.findName("FER_CAPAN");
+    assertTrue(ferCapan.getSequenceAsString().startsWith("MA------SVSAT"));
+
+    SequenceI ferCapanRealigned = realigned.findName("FER_CAPAN");
+    assertTrue(ferCapanRealigned.getSequenceAsString()
+            .startsWith("-------m-A----SVSAT"));
+  }
+}
+
diff --git a/test/jalview/hmmer/testProps.jvprops b/test/jalview/hmmer/testProps.jvprops
new file mode 100644 (file)
index 0000000..05cd493
--- /dev/null
@@ -0,0 +1,88 @@
+#---JalviewX Properties File---
+#Fri Apr 25 09:54:25 BST 2014
+SCREEN_Y=768
+SCREEN_X=936
+SHOW_WSDISCOVERY_ERRORS=true
+LATEST_VERSION=2.8.0b1
+SHOW_CONSERVATION=true
+JALVIEW_RSS_WINDOW_SCREEN_WIDTH=550
+JAVA_CONSOLE_SCREEN_WIDTH=450
+LAST_DIRECTORY=/Volumes/Data/Users/jimp/Documents/testing/Jalview/examples
+ID_ITALICS=true
+SORT_ALIGNMENT=No sort
+SHOW_IDENTITY=true
+WSMENU_BYHOST=false
+SEQUENCE_LINKS=EMBL-EBI Search|http\://www.ebi.ac.uk/ebisearch/search.ebi?db\=allebi&query\=$SEQUENCE_ID$
+SHOW_FULLSCREEN=false
+RECENT_URL=http\://www.jalview.org/examples/exampleFile_2_7.jar
+FONT_NAME=SansSerif
+BLC_JVSUFFIX=true
+VERSION_CHECK=false
+YEAR=2011
+SHOW_DBREFS_TOOLTIP=true
+MSF_JVSUFFIX=true
+SCREENGEOMETRY_HEIGHT=1600
+JAVA_CONSOLE_SCREEN_Y=475
+JAVA_CONSOLE_SCREEN_X=830
+PFAM_JVSUFFIX=true
+PIR_JVSUFFIX=true
+STARTUP_FILE=http\://www.jalview.org/examples/exampleFile_2_3.jar
+JAVA_CONSOLE_SCREEN_HEIGHT=162
+PIR_MODELLER=false
+GAP_SYMBOL=-
+SHOW_QUALITY=true
+SHOW_OCCUPANCY=true
+SHOW_GROUP_CONSERVATION=false
+SHOW_JWS2_SERVICES=true
+SHOW_NPFEATS_TOOLTIP=true
+FONT_STYLE=plain
+ANTI_ALIAS=false
+SORT_BY_TREE=false
+RSBS_SERVICES=|Multi-Harmony|Analysis|Sequence Harmony and Multi-Relief (Brandt et al. 2010)|hseparable,gapCharacter\='-',returns\='ANNOTATION'|?tool\=jalview|http\://zeus.few.vu.nl/programs/shmrwww/index.php?tool\=jalview&groups\=$PARTITION\:min\='2',minsize\='2',sep\=' '$&ali_file\=$ALIGNMENT\:format\='FASTA',writeasfile$
+AUTHORFNAMES=Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton
+JALVIEW_RSS_WINDOW_SCREEN_HEIGHT=328
+SHOW_GROUP_CONSENSUS=false
+SHOW_CONSENSUS_HISTOGRAM=true
+SHOW_OVERVIEW=false
+AUTHORS=J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
+FIGURE_AUTOIDWIDTH=false
+SCREEN_WIDTH=900
+ANNOTATIONCOLOUR_MIN=ffc800
+SHOW_STARTUP_FILE=false
+RECENT_FILE=examples/uniref50.fa\t/Volumes/Data/Users/jimp/Documents/testing/Jalview/examples/RF00031_folded.stk\t/Volumes/Data/Users/jimp/bs_ig_mult.out
+DEFAULT_FILE_FORMAT=FASTA
+SHOW_JAVA_CONSOLE=false
+VERSION=2.8b1
+FIGURE_USERIDWIDTH=
+WSMENU_BYTYPE=false
+DEFAULT_COLOUR=None
+NOQUESTIONNAIRES=true
+JALVIEW_NEWS_RSS_LASTMODIFIED=Apr 23, 2014 2\:53\:26 PM
+BUILD_DATE=01 November 2013
+PILEUP_JVSUFFIX=true
+SHOW_CONSENSUS_LOGO=false
+SCREENGEOMETRY_WIDTH=2560
+SHOW_ANNOTATIONS=true
+JALVIEW_RSS_WINDOW_SCREEN_Y=0
+USAGESTATS=false
+JALVIEW_RSS_WINDOW_SCREEN_X=0
+SHOW_UNCONSERVED=false
+SHOW_JVSUFFIX=true
+DAS_LOCAL_SOURCE=
+SCREEN_HEIGHT=650
+ANNOTATIONCOLOUR_MAX=ff0000
+AUTO_CALC_CONSENSUS=true
+FASTA_JVSUFFIX=true
+DAS_ACTIVE_SOURCE=uniprot\t
+JWS2HOSTURLS=http\://www.compbio.dundee.ac.uk/jabaws
+PAD_GAPS=false
+CLUSTAL_JVSUFFIX=true
+SHOW_ENFIN_SERVICES=true
+FONT_SIZE=10
+RIGHT_ALIGN_IDS=false
+USE_PROXY=false
+WRAP_ALIGNMENT=false
+#DAS_REGISTRY_URL=http\://www.dasregistry.org/das/ # retired 01/05/2015
+DAS_REGISTRY_URL=http\://www.ebi.ac.uk/das-srv/registry/das/
+logs.Jalview.level=DEBUG
+HMMER_PATH=/Users/gmcarstairs/software/hmmer-3.1b2-macosx-intel/binaries
index 7810504..724bae0 100644 (file)
@@ -55,7 +55,7 @@ public class FileFormatsTest
   @Test(groups = "Functional")
   public void testGetReadableFormats()
   {
-    String expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview]";
+    String expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview, HMMER3]";
     FileFormats formats = FileFormats.getInstance();
     assertEquals(formats.getReadableFormats().toString(), expected);
   }
@@ -63,25 +63,25 @@ public class FileFormatsTest
   @Test(groups = "Functional")
   public void testGetWritableFormats()
   {
-    String expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP]";
+    String expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, HMMER3]";
     FileFormats formats = FileFormats.getInstance();
     assertEquals(formats.getWritableFormats(true).toString(), expected);
-    expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, Jalview]";
+    expected = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, Jalview, HMMER3]";
     assertEquals(formats.getWritableFormats(false).toString(), expected);
   }
 
   @Test(groups = "Functional")
   public void testDeregisterFileFormat()
   {
-    String writable = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP]";
-    String readable = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview]";
+    String writable = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, HMMER3]";
+    String readable = "[Fasta, PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview, HMMER3]";
     FileFormats formats = FileFormats.getInstance();
     assertEquals(formats.getWritableFormats(true).toString(), writable);
     assertEquals(formats.getReadableFormats().toString(), readable);
 
     formats.deregisterFileFormat(FileFormat.Fasta.getName());
-    writable = "[PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP]";
-    readable = "[PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview]";
+    writable = "[PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, HMMER3]";
+    readable = "[PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview, HMMER3]";
     assertEquals(formats.getWritableFormats(true).toString(), writable);
     assertEquals(formats.getReadableFormats().toString(), readable);
 
@@ -89,8 +89,8 @@ public class FileFormatsTest
      * re-register the format: it gets added to the end of the list
      */
     formats.registerFileFormat(FileFormat.Fasta);
-    writable = "[PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, Fasta]";
-    readable = "[PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview, Fasta]";
+    writable = "[PFAM, Stockholm, PIR, BLC, AMSA, JSON, PileUp, MSF, Clustal, PHYLIP, HMMER3, Fasta]";
+    readable = "[PFAM, Stockholm, PIR, BLC, AMSA, HTML, RNAML, JSON, PileUp, MSF, Clustal, PHYLIP, GFF or Jalview features, PDB, mmCIF, Jalview, HMMER3, Fasta]";
     assertEquals(formats.getWritableFormats(true).toString(), writable);
     assertEquals(formats.getReadableFormats().toString(), readable);
   }
index b500266..3812a09 100644 (file)
@@ -56,8 +56,17 @@ public class FormatAdapterTest
   {
     try
     {
-      AlignmentI al = new FormatAdapter().readFile("examples/uniref50.fa",
+      AlignmentI al;
+      if (format == FileFormat.HMMER3)
+      {
+        al = new FormatAdapter().readFile("examples/uniref50.hmm",
+                DataSourceType.FILE, FileFormat.HMMER3);
+      }
+      else
+      {
+        al = new FormatAdapter().readFile("examples/uniref50.fa",
               DataSourceType.FILE, FileFormat.Fasta);
+      }
 
       /*
        * 'gap' is the gap character used in the alignment data file here,
@@ -73,8 +82,9 @@ public class FormatAdapterTest
       AlignmentI reloaded = new FormatAdapter().readFile(formatted,
               DataSourceType.PASTE, format);
       List<SequenceI> reread = reloaded.getSequences();
-      assertEquals("Wrong number of reloaded sequences", seqs.length,
-              reread.size());
+        assertEquals("Wrong number of reloaded sequences", seqs.length,
+                reread.size());
+
 
       int i = 0;
       for (SequenceI seq : reread)
@@ -131,7 +141,7 @@ public class FormatAdapterTest
   @DataProvider(name = "formats")
   static Object[][] getFormats()
   {
-    List<FileFormatI> both = new ArrayList<FileFormatI>();
+    List<FileFormatI> both = new ArrayList<>();
     for (FileFormatI format : FileFormats.getInstance().getFormats())
     {
       if (format.isReadable() && format.isWritable()
diff --git a/test/jalview/io/HMMFileTest.java b/test/jalview/io/HMMFileTest.java
new file mode 100644 (file)
index 0000000..cf74f55
--- /dev/null
@@ -0,0 +1,531 @@
+package jalview.io;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import jalview.datamodel.HMMNode;
+import jalview.datamodel.HiddenMarkovModel;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import junit.extensions.PA;
+
+public class HMMFileTest {
+
+  HMMFile fn3;
+
+  HMMFile pKinase;
+
+  HMMFile made1;
+
+  @BeforeClass(alwaysRun = true)
+  public void setUp() throws IOException
+  {
+    fn3 = new HMMFile("test/jalview/io/test_fn3_hmm.txt",
+            DataSourceType.FILE);
+
+    pKinase = new HMMFile("test/jalview/io/test_PKinase_hmm.txt",
+            DataSourceType.FILE);
+
+    made1 = new HMMFile("test/jalview/io/test_MADE1_hmm.txt",
+            DataSourceType.FILE);
+  }
+
+  @Test(groups = "Functional")
+  public void testParse() throws IOException
+  {
+    HiddenMarkovModel hmm = pKinase.getHMM();
+    assertEquals(hmm.getName(), "Pkinase");
+    assertEquals(hmm.getProperty(HMMFile.ACCESSION_NUMBER), "PF00069.17");
+    assertEquals(hmm.getProperty(HMMFile.DESCRIPTION),
+            "Protein kinase domain");
+    assertEquals(hmm.getLength(), 260);
+    assertNull(hmm.getProperty(HMMFile.MAX_LENGTH));
+    assertEquals(hmm.getAlphabetType(), "amino");
+    assertFalse(hmm.getBooleanProperty(HMMFile.REFERENCE_ANNOTATION));
+    assertFalse(hmm.getBooleanProperty(HMMFile.MASKED_VALUE));
+    assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_RESIDUE));
+    assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_STRUCTURE));
+    assertTrue(hmm.getBooleanProperty(HMMFile.MAP));
+    assertEquals(hmm.getProperty(HMMFile.DATE), "Thu Jun 16 11:44:06 2011");
+    assertNull(hmm.getProperty(HMMFile.COMMAND_LOG));
+    assertEquals(hmm.getProperty(HMMFile.NUMBER_OF_SEQUENCES), "54");
+    assertEquals(hmm.getProperty(HMMFile.EFF_NUMBER_OF_SEQUENCES),
+            "3.358521");
+    assertEquals(hmm.getProperty(HMMFile.CHECK_SUM), "3106786190");
+    assertEquals(hmm.getProperty(HMMFile.GATHERING_THRESHOLD),
+            "70.30 70.30");
+    assertEquals(hmm.getProperty(HMMFile.TRUSTED_CUTOFF), "70.30 70.30");
+    assertEquals(hmm.getProperty(HMMFile.NOISE_CUTOFF), "70.20 70.20");
+  
+    assertEquals(hmm.getSymbols(), "ACDEFGHIKLMNPQRSTVWY");
+  
+    assertEquals(hmm.getMatchEmissionProbability(0, 'Y'), 0.16102, 0.001d);
+    assertEquals(hmm.getMatchEmissionProbability(11, 'P'), 0.0130, 0.001d);
+    assertEquals(hmm.getMatchEmissionProbability(24, 'I'), 0.02583, 0.001d);
+    assertEquals(hmm.getMatchEmissionProbability(83, 'C'), 0.008549,
+            0.001d);
+    assertEquals(hmm.getMatchEmissionProbability(332, 'E'), 0.07998,
+            0.001d);
+    assertEquals(hmm.getMatchEmissionProbability(381, 'D'), 0.014465,
+            0.001d);
+    assertEquals(hmm.getMatchEmissionProbability(475, 'Y'), 0.02213,
+            0.001d);
+  
+    assertEquals(hmm.getInsertEmissionProbability(1, 'C'), 0.012, 0.001d);
+    assertEquals(hmm.getInsertEmissionProbability(14, 'H'), 0.02411,
+            0.001d);
+    assertEquals(hmm.getInsertEmissionProbability(23, 'L'), 0.06764,
+            0.001d);
+    assertEquals(hmm.getInsertEmissionProbability(90, 'D'), 0.0623, 0.001d);
+    assertEquals(hmm.getInsertEmissionProbability(374, 'T'), 0.0623,
+            0.001d);
+    assertEquals(hmm.getInsertEmissionProbability(470, 'P'), 0.0647,
+            0.001d);
+  
+    assertEquals(hmm.getStateTransitionProbability(2, 6), 0.3848, 0.001d);
+    assertEquals(hmm.getStateTransitionProbability(38, 3), 0.5382, 0.001d);
+    assertEquals(hmm.getStateTransitionProbability(305, 3), 0.2916, 0.001d);
+    assertEquals(hmm.getStateTransitionProbability(380, 0), 0.99, 0.001d);
+    assertEquals(hmm.getStateTransitionProbability(453, 1), 0.0066, 0.001d);
+  
+    assertEquals(hmm.getNodeMapPosition(3), 3);
+    assertEquals(hmm.getReferenceAnnotation(7), '-');
+    assertEquals(hmm.getConsensusResidue(23), 't');
+    assertEquals(hmm.getMaskedValue(30), '-');
+    assertEquals(hmm.getConsensusStructure(56), 'S');
+  
+    assertEquals(hmm.getNodeMapPosition(78), 136);
+    assertEquals(hmm.getReferenceAnnotation(93), '-');
+    assertEquals(hmm.getConsensusResidue(145), 'a');
+    assertEquals(hmm.getMaskedValue(183), '-');
+    assertEquals(hmm.getConsensusStructure(240), 'H');
+  }
+
+  /**
+   * Test that Jalview can parse an HMM file even with a bunch of 'mandatory'
+   * fields missing (including no MAP annotation or // terminator line)
+   * 
+   * @throws IOException
+   */
+  @Test(groups = "Functional")
+  public void testParse_minimalFile() throws IOException
+  {
+    /*
+     * ALPH is absent, alphabet inferred from HMM header line
+     * Optional COMPO line is absent
+     * first line after HMM is a guide line for readability
+     * next line is BEGIN node insert emissions
+     * next line is BEGIN node transitions
+     * next line is first sequence node match emissions 1.1 1.2 1.3
+     * next line is first sequence node insert emissions 1.4 1.5 1.6
+     * last line is first sequence node transitions
+     */
+    //@formatter:off
+    String hmmData = 
+            "HMMER3\n" +
+            "HMM P M J\n" +
+            // both spec and parser require a line after the HMM line
+            " m->m m->i m->d i->m i->i d->m d->d\n" +
+            " 0.1 0.2 0.3\n" + 
+            " 0.4 0.5 0.6 0.7 0.8 0.9 0.95\n" + 
+            " 1 1.1 1.2 1.3 - - - - -\n" + 
+            " 1.4 1.5 1.6\n" + 
+            " 1.7 1.8 1.9 2.0 2.1 2.2 2.3\n" +
+            " 2 1.01 1.02 1.03 - - - - -\n" + 
+            " 1.04 1.05 1.06\n" + 
+            " 1.7 1.8 1.9 2.0 2.1 2.2 2.3\n";
+    //@formatter:on
+    HMMFile parser = new HMMFile(hmmData, DataSourceType.PASTE);
+    HiddenMarkovModel hmm = parser.getHMM();
+    assertNotNull(hmm);
+    assertEquals(hmm.getSymbols(), "PMJ");
+    // no LENG property: this should return node count excluding BEGIN node
+    assertEquals(hmm.getLength(), 2);
+
+    // node 1 (implicitly mapped to column 0)
+    double prob = hmm.getMatchEmissionProbability(0, 'p');
+    assertEquals(prob, Math.pow(Math.E, -1.1));
+    prob = hmm.getInsertEmissionProbability(0, 'J');
+    assertEquals(prob, Math.pow(Math.E, -1.6));
+
+    // node 2 (implicitly mapped to column 1)
+    prob = hmm.getMatchEmissionProbability(1, 'M');
+    assertEquals(prob, Math.pow(Math.E, -1.02));
+    prob = hmm.getInsertEmissionProbability(1, 'm');
+    assertEquals(prob, Math.pow(Math.E, -1.05));
+  }
+  
+  @Test(groups = "Functional")
+  public void testParseHeaderLines_amino() throws IOException
+  {
+    FileReader fr = new FileReader(
+            new File("test/jalview/io/test_fn3_hmm.txt"));
+    BufferedReader br = new BufferedReader(fr);
+    HiddenMarkovModel hmm = new HiddenMarkovModel();
+    HMMFile testee = new HMMFile();
+    PA.setValue(testee, "hmm", hmm);
+    testee.parseHeaderLines(br);
+    br.close();
+    fr.close();
+  
+    assertEquals(hmm.getName(), "fn3");
+    assertEquals(hmm.getProperty(HMMFile.ACCESSION_NUMBER), "PF00041.13");
+    assertEquals(hmm.getProperty(HMMFile.DESCRIPTION),
+            "Fibronectin type III domain");
+    assertEquals(hmm.getProperty(HMMFile.LENGTH), "86");
+    assertNull(hmm.getProperty(HMMFile.MAX_LENGTH));
+    assertEquals(hmm.getAlphabetType(), "amino");
+    assertFalse(hmm.getBooleanProperty(HMMFile.REFERENCE_ANNOTATION));
+    assertFalse(hmm.getBooleanProperty(HMMFile.MASKED_VALUE));
+    assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_RESIDUE));
+    assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_STRUCTURE));
+
+    assertTrue(hmm.getBooleanProperty(HMMFile.MAP));
+    assertEquals(hmm.getProperty(HMMFile.DATE), "Fri Jun 20 08:22:31 2014");
+    assertNull(hmm.getProperty(HMMFile.COMMAND_LOG));
+    assertEquals(hmm.getProperty(HMMFile.NUMBER_OF_SEQUENCES), "106");
+    assertEquals(hmm.getProperty(HMMFile.EFF_NUMBER_OF_SEQUENCES),
+            "11.415833");
+    assertEquals(hmm.getProperty(HMMFile.CHECK_SUM), "3564431818");
+    assertEquals(hmm.getProperty(HMMFile.GATHERING_THRESHOLD), "8.00 7.20");
+    assertEquals(hmm.getProperty(HMMFile.TRUSTED_CUTOFF), "8.00 7.20");
+    assertEquals(hmm.getProperty(HMMFile.NOISE_CUTOFF), "7.90 7.90");
+    assertEquals(hmm.getViterbi(), "-9.7737  0.71847");
+    assertEquals(hmm.getMSV(), "-9.4043  0.71847");
+    assertEquals(hmm.getForward(), "-3.8341  0.71847");
+  }
+  
+  @Test(groups = "Functional")
+  public void testParseHeaderLines_dna() throws IOException
+  {
+    FileReader fr = new FileReader(
+            new File("test/jalview/io/test_MADE1_hmm.txt"));
+    BufferedReader br = new BufferedReader(fr);
+    HiddenMarkovModel hmm = new HiddenMarkovModel();
+    HMMFile testee = new HMMFile();
+    PA.setValue(testee, "hmm", hmm);
+    testee.parseHeaderLines(br);
+    br.close();
+    fr.close();
+  
+    assertEquals(hmm.getName(), "MADE1");
+    assertEquals(hmm.getProperty(HMMFile.ACCESSION_NUMBER),
+            "DF0000629.2");
+    assertEquals(hmm.getProperty(HMMFile.DESCRIPTION),
+            "MADE1 (MAriner Derived Element 1), a TcMar-Mariner DNA transposon");
+    assertEquals(hmm.getProperty(HMMFile.LENGTH), "80");
+    assertEquals(hmm.getProperty(HMMFile.MAX_LENGTH), "426");
+    assertEquals(hmm.getAlphabetType(), "DNA");
+    assertTrue(hmm.getBooleanProperty(HMMFile.REFERENCE_ANNOTATION));
+    assertFalse(hmm.getBooleanProperty(HMMFile.MASKED_VALUE));
+    assertTrue(hmm.getBooleanProperty(HMMFile.CONSENSUS_RESIDUE));
+    assertFalse(hmm.getBooleanProperty(HMMFile.CONSENSUS_STRUCTURE));
+    assertTrue(hmm.getBooleanProperty(HMMFile.MAP));
+    assertEquals(hmm.getProperty(HMMFile.DATE), "Tue Feb 19 20:33:41 2013");
+    assertNull(hmm.getProperty(HMMFile.COMMAND_LOG));
+    assertEquals(hmm.getProperty(HMMFile.NUMBER_OF_SEQUENCES), "1997");
+    assertEquals(hmm.getProperty(HMMFile.EFF_NUMBER_OF_SEQUENCES), "3.911818");
+    assertEquals(hmm.getProperty(HMMFile.CHECK_SUM), "3015610723");
+    assertEquals(hmm.getProperty(HMMFile.GATHERING_THRESHOLD),
+            "2.324 4.234");
+    assertEquals(hmm.getProperty(HMMFile.TRUSTED_CUTOFF), "2.343 1.212");
+    assertEquals(hmm.getProperty(HMMFile.NOISE_CUTOFF), "2.354 5.456");
+    assertEquals(hmm.getViterbi(), "-9.3632  0.71858");
+    assertEquals(hmm.getMSV(), "-8.5786  0.71858");
+    assertEquals(hmm.getForward(), "-3.4823  0.71858");
+  }
+  
+  @Test(groups = "Functional")
+  public void testFillList() throws IOException
+  {
+    Scanner scanner1 = new Scanner("1.3 2.4 5.3 3.9 9.8 4.7 4.3 2.3 6.9");
+    ArrayList<Double> filledArray = new ArrayList<>();
+  
+    filledArray.add(0.27253);
+    filledArray.add(0.0907);
+    filledArray.add(0.00499);
+    filledArray.add(0.02024);
+    filledArray.add(0.00005);
+    filledArray.add(0.00909);
+    filledArray.add(0.01357);
+    filledArray.add(0.10026);
+    filledArray.add(0.001);
+  
+    double[] testList = HMMFile.parseDoubles(scanner1, 9);
+
+    for (int i = 0; i < 9; i++)
+    {
+      assertEquals(testList[i], filledArray.get(i), 0.001d);
+    }
+
+    filledArray.clear();
+    scanner1.close();
+  
+    Scanner scanner2 = new Scanner(
+            "1.346 5.554 35.345 5.64 1.4");
+    filledArray.add(0.2603);
+    filledArray.add(0.00387);
+    filledArray.add(0d);
+    filledArray.add(0.00355);
+    filledArray.add(0.2466);
+  
+    testList = HMMFile.parseDoubles(scanner2, 5);
+
+    for (int i = 0; i < 5; i++)
+    {
+      assertEquals(testList[i], filledArray.get(i), 0.001d);
+    }
+  }
+  
+  @Test(groups = "Functional")
+  public void testParseModel() throws IOException
+  {
+    FileReader fr = new FileReader(
+            new File("test/jalview/io/test_MADE1_hmm.txt"));
+    BufferedReader br = new BufferedReader(fr);
+    HiddenMarkovModel testHMM = new HiddenMarkovModel();
+    String line = null;
+    do
+    {
+      line = br.readLine(); // skip header lines up to HMM plus one
+    } while (!line.startsWith("HMM "));
+    br.readLine();
+
+    made1.parseModel(br);
+    testHMM = made1.getHMM();
+
+    br.close();
+    fr.close();
+  
+    assertEquals(testHMM.getMatchEmissionProbability(1, 'C'), 0.09267,
+            0.001d);
+    assertEquals(testHMM.getMatchEmissionProbability(25, 'G'), 0.07327,
+            0.001d);
+    assertEquals(testHMM.getMatchEmissionProbability(1092, 'C'), 0.04184,
+            0.001d);
+    assertEquals(testHMM.getMatchEmissionProbability(1107, 'G'), 0.07,
+            0.001d);
+  
+    assertEquals(testHMM.getInsertEmissionProbability(0, 'G'), 0.25,
+            0.001d);
+    assertEquals(testHMM.getInsertEmissionProbability(247, 'T'), 0.2776,
+            0.001d);
+    assertEquals(testHMM.getInsertEmissionProbability(1096, 'T'), 0.25,
+            0.001d);
+    assertEquals(testHMM.getInsertEmissionProbability(1111, 'T'), 0.25,
+            0.001d);
+
+    assertEquals(testHMM.getStateTransitionProbability(1, 0), 0.9634,
+            0.001d);
+    assertEquals(testHMM.getStateTransitionProbability(5, 1), 0.0203,
+            0.001d);
+    assertEquals(testHMM.getStateTransitionProbability(14, 3), 0.2515,
+            0.001d);
+    assertEquals(testHMM.getStateTransitionProbability(65, 4), 0.78808,
+            0.001d);
+    assertEquals(testHMM.getStateTransitionProbability(1080, 2), 0.01845,
+            0.001d);
+    assertEquals(testHMM.getStateTransitionProbability(1111, 6),
+            Double.NEGATIVE_INFINITY);
+  }
+  
+  @Test(groups = "Functional")
+  public void testParseAnnotations()
+  {
+    HMMFile testFile = new HMMFile();
+    HiddenMarkovModel hmm = new HiddenMarkovModel();
+    PA.setValue(testFile, "hmm", hmm);
+
+    List<HMMNode> nodes = new ArrayList<>();
+    nodes.add(new HMMNode()); // BEGIN node
+  
+    hmm.setProperty(HMMFile.CONSENSUS_RESIDUE, "yes");
+    hmm.setProperty(HMMFile.MAP, "yes");
+    hmm.setProperty(HMMFile.REFERENCE_ANNOTATION, "yes");
+    hmm.setProperty(HMMFile.CONSENSUS_STRUCTURE, "yes");
+    hmm.setProperty(HMMFile.MASKED_VALUE, "yes");
+    Scanner scanner = new Scanner("1345 t t t t");
+    HMMNode node = new HMMNode();
+    nodes.add(node);
+    testFile.parseAnnotations(scanner, node);
+  
+    hmm.setProperty(HMMFile.CONSENSUS_RESIDUE, "yes");
+    hmm.setProperty(HMMFile.MAP, "no");
+    hmm.setProperty(HMMFile.REFERENCE_ANNOTATION, "yes");
+    hmm.setProperty(HMMFile.CONSENSUS_STRUCTURE, "no");
+    hmm.setProperty(HMMFile.MASKED_VALUE, "no");
+    Scanner scanner2 = new Scanner("- y x - -");
+    node = new HMMNode();
+    nodes.add(node);
+    testFile.parseAnnotations(scanner2, node);
+
+    hmm.setNodes(nodes);
+
+    assertEquals(hmm.getNodeMapPosition(1), 1345);
+    assertEquals(hmm.getConsensusResidue(1), 't');
+    assertEquals(hmm.getReferenceAnnotation(1), 't');
+    assertEquals(hmm.getMaskedValue(1), 't');
+    assertEquals(hmm.getConsensusStructure(1), 't');
+  
+    scanner.close();
+  }
+  
+  /**
+   * tests to see if file produced by the output matches the file from the input
+   * 
+   * @throws IOException
+   */
+  @Test(groups = "Functional")
+  public void testPrint_roundTrip() throws IOException
+  {
+    String output = pKinase.print();
+    HMMFile pKinaseClone = new HMMFile(
+            new FileParse(output, DataSourceType.PASTE));
+    HiddenMarkovModel pKinaseHMM = pKinase.getHMM();
+    HiddenMarkovModel pKinaseCloneHMM = pKinaseClone.getHMM();
+  
+    checkModelsMatch(pKinaseHMM, pKinaseCloneHMM);
+  }
+
+  /**
+   * A helper method to check two HMM models have the same values
+   * 
+   * @param model1
+   * @param model2
+   */
+  protected void checkModelsMatch(HiddenMarkovModel model1,
+          HiddenMarkovModel model2)
+  {
+    assertEquals(model1.getLength(), model2.getLength());
+
+    for (int i = 0; i < model1.getLength(); i++)
+    {
+      String msg = "For Node" + i;
+      assertEquals(model1.getNode(i).getMatchEmissions(),
+              model2.getNode(i).getMatchEmissions(), msg);
+      assertEquals(model1.getNode(i).getInsertEmissions(),
+              model2.getNode(i).getInsertEmissions(), msg);
+      assertEquals(model1.getNode(i).getStateTransitions(),
+              model2.getNode(i).getStateTransitions(), msg);
+  
+      if (i > 0)
+      {
+        assertEquals(model1.getNodeMapPosition(i),
+                model2.getNodeMapPosition(i), msg);
+        assertEquals(model1.getReferenceAnnotation(i),
+                model2.getReferenceAnnotation(i), msg);
+        assertEquals(model1.getConsensusResidue(i),
+                model2.getConsensusResidue(i), msg);
+      }
+    }
+  }
+  
+  @Test(groups = "Functional")
+  public void testAppendProperties() throws FileNotFoundException
+  {
+    StringBuilder sb = new StringBuilder();
+    fn3.appendProperties(sb);
+
+    Scanner testScanner = new Scanner(sb.toString());
+  
+    String[] expected = new String[] { "HMMER3/f [3.1b1 | May 2013]",
+        "NAME  fn3", "ACC   PF00041.13",
+        "DESC  Fibronectin type III domain", "LENG  86", "ALPH  amino",
+        "RF    no", "MM    no", "CONS  yes", "CS    yes", "MAP   yes",
+        "DATE  Fri Jun 20 08:22:31 2014", "NSEQ  106", "EFFN  11.415833",
+        "CKSUM 3564431818", "GA    8.00 7.20", "TC    8.00 7.20",
+        "NC    7.90 7.90", "STATS LOCAL MSV       -9.4043  0.71847",
+        "STATS LOCAL VITERBI   -9.7737  0.71847",
+        "STATS LOCAL FORWARD   -3.8341  0.71847" };
+  
+    for (String value : expected)
+    {
+      assertEquals(testScanner.nextLine(), value);
+    }
+  
+    testScanner.close();
+  }
+  
+  @Test(groups = "Functional")
+  public void testAppendModelAsString() throws FileNotFoundException
+  {
+    StringBuilder sb = new StringBuilder();
+    fn3.appendModelAsString(sb);
+    String string = sb.toString();
+
+    assertEquals(findValue(2, 2, 2, string), "4.42225");
+    assertEquals(findValue(12, 14, 1, string), "2.79307");
+    assertEquals(findValue(6, 24, 3, string), "0.48576");
+    assertEquals(findValue(19, 33, 2, string), "4.58477");
+    assertEquals(findValue(20, 64, 2, string), "3.61505");
+    assertEquals(findValue(3, 72, 3, string), "6.81068");
+    assertEquals(findValue(10, 80, 2, string), "2.69355");
+    assertEquals(findValue(16, 65, 1, string), "2.81003");
+    assertEquals(findValue(14, 3, 1, string), "2.69012");
+    assertEquals(findValue(11, 32, 1, string), "4.34805");
+  }
+  
+  /**
+   * A helper method to find a token in the model string
+   * 
+   * @param symbolIndex
+   *          index of symbol being searched. First symbol has index 1.
+   * @param nodeIndex
+   *          index of node being searched. Begin node has index 0. First node
+   *          has index 1.
+   * @param line
+   *          index of line being searched in node. First line has index 1.
+   * @param model
+   *          string model being searched
+   * @return value at specified position
+   */
+  private String findValue(int symbolIndex, int nodeIndex, int line,
+          String model)
+  {
+    String value = "";
+    Scanner scanner = new Scanner(model);
+    scanner.nextLine();
+    scanner.nextLine();
+  
+    for (int lineIndex = 0; lineIndex < line - 1; lineIndex++)
+    {
+      scanner.nextLine();
+    }
+    for (int node = 0; node < nodeIndex; node++)
+    {
+      scanner.nextLine();
+      scanner.nextLine();
+      scanner.nextLine();
+    }
+  
+    for (int symbol = 0; symbol < symbolIndex; symbol++)
+    {
+      value = scanner.next();
+      if ("COMPO".equals(value))
+      {
+        scanner.next();
+      }
+      else if (value.length() < 7)
+      {
+        scanner.next();
+      }
+    }
+    scanner.close();
+    return value;
+  }
+}
+
index 5e835bf..4cd5b54 100644 (file)
@@ -494,8 +494,8 @@ public class JSONFileTest
             + actualGrp.getColourText());
     System.out.println(expectedGrp.getDisplayBoxes() + " | "
             + actualGrp.getDisplayBoxes());
-    System.out.println(expectedGrp.getIgnoreGapsConsensus() + " | "
-            + actualGrp.getIgnoreGapsConsensus());
+    System.out.println(expectedGrp.isIgnoreGapsConsensus() + " | "
+            + actualGrp.isIgnoreGapsConsensus());
     System.out.println(expectedGrp.getSequences().size() + " | "
             + actualGrp.getSequences().size());
     System.out.println(expectedGrp.getStartRes() + " | "
@@ -512,8 +512,8 @@ public class JSONFileTest
     if (expectedGrp.getName().equals(actualGrp.getName())
             && expectedGrp.getColourText() == actualGrp.getColourText()
             && expectedGrp.getDisplayBoxes() == actualGrp.getDisplayBoxes()
-            && expectedGrp.getIgnoreGapsConsensus() == actualGrp
-                    .getIgnoreGapsConsensus()
+            && expectedGrp.isIgnoreGapsConsensus() == actualGrp
+                    .isIgnoreGapsConsensus()
             && colourSchemeMatches
             && expectedGrp.getSequences().size() == actualGrp
                     .getSequences().size()
index 53bb0e7..3a727b4 100644 (file)
@@ -33,7 +33,9 @@ import jalview.api.FeatureColourI;
 import jalview.api.ViewStyleI;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.HiddenSequences;
+import jalview.datamodel.Mapping;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.PDBEntry.Type;
 import jalview.datamodel.SequenceCollectionI;
@@ -44,7 +46,6 @@ import jalview.datamodel.features.FeatureMatcher;
 import jalview.datamodel.features.FeatureMatcherSet;
 import jalview.datamodel.features.FeatureMatcherSetI;
 import jalview.gui.AlignFrame;
-import jalview.gui.AlignViewport;
 import jalview.gui.AlignmentPanel;
 import jalview.gui.Desktop;
 import jalview.gui.FeatureRenderer;
@@ -79,6 +80,8 @@ import org.testng.AssertJUnit;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import junit.extensions.PA;
+
 @Test(singleThreaded = true)
 public class Jalview2xmlTests extends Jalview2xmlBase
 {
@@ -796,7 +799,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             "examples/uniref50.fa", DataSourceType.FILE);
 
-    AlignViewport av = af.getViewport();
+    AlignViewportI av = af.getViewport();
     AlignmentI al = av.getAlignment();
 
     /*
@@ -883,7 +886,8 @@ public class Jalview2xmlTests extends Jalview2xmlBase
    * @throws IOException
    */
   @Test(groups = { "Functional" })
-  public void testSaveLoadFeatureColoursAndFilters() throws IOException
+  public void testStoreAndRecoverFeatureColoursAndFilters()
+          throws IOException
   {
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
             ">Seq1\nACDEFGHIKLM", DataSourceType.PASTE);
@@ -1035,4 +1039,57 @@ public class Jalview2xmlTests extends Jalview2xmlBase
     addFeature(seq, featureType, score++);
     addFeature(seq, featureType, score);
   }
+
+  /**
+   * Load an HMM profile to an alignment, and confirm it is correctly restored
+   * when reloaded from project
+   * 
+   * @throws IOException
+   */
+  @Test(groups = { "Functional" })
+  public void testStoreAndRecoverHmmProfile() throws IOException
+  {
+    Desktop.instance.closeAll_actionPerformed(null);
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+  
+    AlignViewportI av = af.getViewport();
+    AlignmentI al = av.getAlignment();
+
+    /*
+     * mimic drag and drop of hmm file on to alignment
+     */
+    AlignFrame af2 = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.hmm", DataSourceType.FILE);
+    al.insertSequenceAt(0,
+            af2.getViewport().getAlignment().getSequenceAt(0));
+
+    /*
+     * check it loaded in
+     */
+    SequenceI hmmSeq = al.getSequenceAt(0);
+    assertTrue(hmmSeq.hasHMMProfile());
+    HiddenMarkovModel hmm = hmmSeq.getHMM();
+    assertSame(hmm.getConsensusSequence(), hmmSeq);
+
+    /*
+     * save project, close windows, reload project, verify
+     */
+    File tfile = File.createTempFile("testStoreAndRecoverHmmProfile",
+            ".jvp");
+    tfile.deleteOnExit();
+    new Jalview2XML(false).saveState(tfile);
+    Desktop.instance.closeAll_actionPerformed(null);
+    af = new FileLoader().LoadFileWaitTillLoaded(tfile.getAbsolutePath(),
+            DataSourceType.FILE);
+    Assert.assertNotNull(af, "Failed to reload project");
+
+    hmmSeq = al.getSequenceAt(0);
+    assertTrue(hmmSeq.hasHMMProfile());
+    assertSame(hmm.getConsensusSequence(), hmmSeq);
+    Mapping mapToHmmConsensus = (Mapping) PA.getValue(hmm,
+            "mapToHmmConsensus");
+    assertNotNull(mapToHmmConsensus);
+    assertSame(mapToHmmConsensus.getTo(), hmmSeq.getDatasetSequence());
+  }
 }
index 4273e6c..1c9c79d 100644 (file)
@@ -22,17 +22,22 @@ package jalview.io;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertNull;
 import static org.testng.AssertJUnit.assertTrue;
 import static org.testng.AssertJUnit.fail;
 
+import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
+import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.JvOptionPane;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.HashMap;
@@ -230,8 +235,8 @@ public class StockholmFileTest
     // we might want to revise this in future
     int aa_new_size = (aa_new == null ? 0 : aa_new.length);
     int aa_original_size = (aa_original == null ? 0 : aa_original.length);
-    Map<Integer, BitSet> orig_groups = new HashMap<Integer, BitSet>();
-    Map<Integer, BitSet> new_groups = new HashMap<Integer, BitSet>();
+    Map<Integer, BitSet> orig_groups = new HashMap<>();
+    Map<Integer, BitSet> new_groups = new HashMap<>();
 
     if (aa_new != null && aa_original != null)
     {
@@ -654,4 +659,273 @@ public class StockholmFileTest
     testAlignmentEquivalence(al, newAl, true, true, true);
 
   }
+
+  @Test(groups = { "Functional" })
+  public void testTypeToDescription()
+  {
+    assertEquals("Secondary Structure",
+            StockholmFile.typeToDescription("SS"));
+    assertEquals("Surface Accessibility",
+            StockholmFile.typeToDescription("SA"));
+    assertEquals("transmembrane", StockholmFile.typeToDescription("TM"));
+    assertEquals("Posterior Probability",
+            StockholmFile.typeToDescription("PP"));
+    assertEquals("ligand binding", StockholmFile.typeToDescription("LI"));
+    assertEquals("active site", StockholmFile.typeToDescription("AS"));
+    assertEquals("intron", StockholmFile.typeToDescription("IN"));
+    assertEquals("interacting residue",
+            StockholmFile.typeToDescription("IR"));
+    assertEquals("accession", StockholmFile.typeToDescription("AC"));
+    assertEquals("organism", StockholmFile.typeToDescription("OS"));
+    assertEquals("class", StockholmFile.typeToDescription("CL"));
+    assertEquals("description", StockholmFile.typeToDescription("DE"));
+    assertEquals("reference", StockholmFile.typeToDescription("DR"));
+    assertEquals("look", StockholmFile.typeToDescription("LO"));
+    assertEquals("Reference Positions",
+            StockholmFile.typeToDescription("RF"));
+
+    // case-sensitive:
+    assertEquals("Rf", StockholmFile.typeToDescription("Rf"));
+    assertEquals("junk", StockholmFile.typeToDescription("junk"));
+    assertEquals("", StockholmFile.typeToDescription(""));
+    assertNull(StockholmFile.typeToDescription(null));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testDescriptionToType()
+  {
+    assertEquals("SS",
+            StockholmFile.descriptionToType("Secondary Structure"));
+    assertEquals("SA",
+            StockholmFile.descriptionToType("Surface Accessibility"));
+    assertEquals("TM", StockholmFile.descriptionToType("transmembrane"));
+
+    // test is not case-sensitive:
+    assertEquals("SS",
+            StockholmFile.descriptionToType("secondary structure"));
+
+    // test is white-space sensitive:
+    assertNull(StockholmFile.descriptionToType("secondary structure "));
+
+    assertNull(StockholmFile.descriptionToType("any old junk"));
+    assertNull(StockholmFile.descriptionToType(""));
+    assertNull(StockholmFile.descriptionToType(null));
+  }
+
+  @Test(groups = { "Functional" })
+  public void testPrint()
+  {
+    SequenceI seq1 = new Sequence("seq1", "LKMF-RS-Q");
+    SequenceI seq2 = new Sequence("seq2/10-15", "RRS-LIP-");
+    SequenceI[] seqs = new SequenceI[] { seq1, seq2 };
+    AlignmentI al = new Alignment(seqs);
+
+    StockholmFile testee = new StockholmFile(al);
+
+    /*
+     * basic output (sequences only): 
+     * sequence ids are padded with 9 spaces more than the widest id
+     */
+    String output = testee.print(seqs, true);
+    String expected = "# STOCKHOLM 1.0\n" + "seq1/1-7           LKMF-RS-Q\n"
+            + "seq2/10-15         RRS-LIP-\n//\n";
+    assertEquals(expected, output);
+    
+    /*
+     * add some dbrefs
+     */
+    seq1.addDBRef(new DBRefEntry("PFAM", "1", "PF00111"));
+    seq1.addDBRef(new DBRefEntry("UNIPROT", "1", "P83527"));
+    seq2.addDBRef(new DBRefEntry("RFAM", "1", "AY119185.1"));
+    seq2.addDBRef(new DBRefEntry("EMBL", "1", "AF125575"));
+    output = testee.print(seqs, true);
+    // PFAM and RFAM dbrefs should be output as AC, others as DR
+    expected = "# STOCKHOLM 1.0\n" + "#=GS seq1/1-7     AC PF00111\n"
+            + "#=GS seq1/1-7     DR UNIPROT ; P83527\n"
+            + "#=GS seq2/10-15   AC AY119185.1\n"
+            + "#=GS seq2/10-15   DR EMBL ; AF125575\n"
+            + "seq1/1-7           LKMF-RS-Q\n"
+            + "seq2/10-15         RRS-LIP-\n//\n";
+    assertEquals(expected, output);
+
+    /*
+     * add some sequence and alignment annotation
+     */
+    Annotation[] anns = new Annotation[5];
+    for (int i = 0; i < anns.length; i++)
+    {
+      anns[i] = new Annotation(String.valueOf((char) ('B' + i)),
+              "Desc " + i,
+              (char) ('C' + i), i + 3);
+    }
+
+    // expect "secondary structure" to be output as #=GR seqid SS
+    // using the secondary structure character (CDEFG) not display char (BCDEF)
+    AlignmentAnnotation aa1 = new AlignmentAnnotation("secondary structure",
+            "ssdesc", anns);
+    aa1.sequenceRef = seq1;
+    seq1.addAlignmentAnnotation(aa1);
+    al.addAnnotation(aa1);
+
+    // "sec structure" should not be output as no corresponding feature id
+    AlignmentAnnotation aa2 = new AlignmentAnnotation("sec structure",
+            "ssdesc", anns);
+    aa2.sequenceRef = seq2;
+    seq2.addAlignmentAnnotation(aa2);
+    al.addAnnotation(aa2);
+
+    // alignment annotation for Reference Positions: output as #=GC RF
+    AlignmentAnnotation aa3 = new AlignmentAnnotation("reference positions",
+            "refpos", anns);
+    al.addAnnotation(aa3);
+
+    // 'seq' annotation: output as seq_cons
+    AlignmentAnnotation aa4 = new AlignmentAnnotation("seq", "seqdesc",
+            anns);
+    al.addAnnotation(aa4);
+
+    // 'intron' annotation: output as IN_cons
+    AlignmentAnnotation aa5 = new AlignmentAnnotation("intron",
+            "introndesc", anns);
+    al.addAnnotation(aa5);
+
+    // 'binding site' annotation: output as binding_site
+    AlignmentAnnotation aa6 = new AlignmentAnnotation("binding site",
+            "bindingdesc", anns);
+    al.addAnnotation(aa6);
+
+    // 'autocalc' annotation should not be output
+    AlignmentAnnotation aa7 = new AlignmentAnnotation("Consensus",
+            "consensusdesc", anns);
+    aa7.autoCalculated = true;
+    al.addAnnotation(aa7);
+
+    // hidden annotation should not be output
+    AlignmentAnnotation aa8 = new AlignmentAnnotation("domains",
+            "domaindesc", anns);
+    aa8.visible = false;
+    al.addAnnotation(aa8);
+
+    output = testee.print(seqs, true);
+    //@formatter:off
+    expected = 
+            "# STOCKHOLM 1.0\n" 
+            + "#=GS seq1/1-7     AC PF00111\n"
+            + "#=GS seq1/1-7     DR UNIPROT ; P83527\n"
+            + "#=GS seq2/10-15   AC AY119185.1\n"
+            + "#=GS seq2/10-15   DR EMBL ; AF125575\n"
+            + "#=GR seq1/1-7 SS   CDEFG\n"
+            + "seq1/1-7           LKMF-RS-Q\n"
+            + "seq2/10-15         RRS-LIP-\n" 
+            + "#=GC RF            BCDEF\n" + "#=GC seq_cons      BCDEF\n"
+            + "#=GC IN_cons       BCDEF\n" + "#=GC binding_site  BCDEF\n"
+            + "//\n";
+    //@formatter:on
+    assertEquals(expected, output);
+  }
+
+  @Test(groups = "Functional")
+  public void testGetAnnotationCharacter()
+  {
+    SequenceI seq = new Sequence("seq", "abc--def-");
+
+    Annotation[] ann = new Annotation[8];
+    ann[1] = new Annotation("Z", "desc", 'E', 1f);
+    ann[2] = new Annotation("Q", "desc", ' ', 1f);
+    ann[4] = new Annotation("", "desc", 'E', 1f);
+    ann[6] = new Annotation("ZH", "desc", 'E', 1f);
+
+    /*
+     * null annotation in column (not Secondary Structure annotation)
+     * should answer sequence character, or '-' if null sequence
+     */
+    assertEquals('-',
+            StockholmFile.getAnnotationCharacter("RF", 0, ann[0], null));
+    assertEquals('d',
+            StockholmFile.getAnnotationCharacter("RF", 5, ann[5], seq));
+    assertEquals('-',
+            StockholmFile.getAnnotationCharacter("RF", 8, null, seq));
+
+    /*
+     * null annotation in column (SS annotation) should answer underscore
+     */
+    assertEquals('_',
+            StockholmFile.getAnnotationCharacter("SS", 0, ann[0], seq));
+
+    /*
+     * SS secondary structure symbol
+     */
+    assertEquals('E',
+            StockholmFile.getAnnotationCharacter("SS", 1, ann[1], seq));
+
+    /*
+     * no SS symbol, use label instead 
+     */
+    assertEquals('Q',
+            StockholmFile.getAnnotationCharacter("SS", 2, ann[2], seq));
+
+    /*
+     * SS with 2 character label - second character overrides SS symbol 
+     */
+    assertEquals('H',
+            StockholmFile.getAnnotationCharacter("SS", 6, ann[6], seq));
+
+    /*
+     * empty display character, not SS - answers '.'
+     */
+    assertEquals('.',
+            StockholmFile.getAnnotationCharacter("RF", 4, ann[4], seq));
+  }
+
+  /**
+   * Test to verify that gaps are input/output as underscore in STO annotation
+   * 
+   * @throws IOException
+   */
+  @Test(groups = "Functional")
+  public void testRoundtripWithGaps() throws IOException
+  {
+    /*
+     * small extract from RF00031_folded.stk
+     */
+    // @formatter:off
+    String stoData = 
+            "# STOCKHOLM 1.0\n" +
+            "#=GR B.taurus.4 SS .._((.))_\n" +
+            "B.taurus.4         AC.UGCGU.\n" +
+            "#=GR B.taurus.5 SS ..((_._))\n" +
+            "B.taurus.5         ACUU.G.CG\n" +
+        "//\n";
+    // @formatter:on
+    StockholmFile parser = new StockholmFile(stoData, DataSourceType.PASTE);
+    SequenceI[] seqs = parser.getSeqsAsArray();
+    assertEquals(2, seqs.length);
+
+    /*
+     * B.taurus.4 has a trailing gap
+     * rendered as underscore in Stockholm annotation
+     */
+    assertEquals("AC.UGCGU.", seqs[0].getSequenceAsString());
+    AlignmentAnnotation[] anns = seqs[0].getAnnotation();
+    assertEquals(1, anns.length);
+    AlignmentAnnotation taurus4SS = anns[0];
+    assertEquals(9, taurus4SS.annotations.length);
+    assertEquals(" .", taurus4SS.annotations[0].displayCharacter);
+    assertNull(taurus4SS.annotations[2]); // gapped position
+    assertNull(taurus4SS.annotations[8]); // gapped position
+    assertEquals('(', taurus4SS.annotations[3].secondaryStructure);
+    assertEquals("(", taurus4SS.annotations[3].displayCharacter);
+    assertEquals(')', taurus4SS.annotations[7].secondaryStructure);
+
+    /*
+     * output as Stockholm and verify it matches the original input
+     * (gaps output as underscore in annotation lines)
+     * note: roundtrip test works with the input lines ordered as above;
+     * can also parse in other orders, but then input doesn't match output
+     */
+    AlignmentFileWriterI afile = FileFormat.Stockholm
+            .getWriter(new Alignment(seqs));
+    String output = afile.print(seqs, false);
+    assertEquals(stoData, output);
+  }
 }
diff --git a/test/jalview/io/test_MADE1_hmm.txt b/test/jalview/io/test_MADE1_hmm.txt
new file mode 100644 (file)
index 0000000..32231db
--- /dev/null
@@ -0,0 +1,268 @@
+HMMER3/f [3.1 | February 2013]
+NAME  MADE1
+ACC   DF0000629.2
+DESC  MADE1 (MAriner Derived Element 1), a TcMar-Mariner DNA transposon
+LENG  80
+MAXL  426
+ALPH  DNA
+RF    yes
+MM    no
+CONS  yes
+CS    no
+MAP   yes
+DATE  Tue Feb 19 20:33:41 2013
+NSEQ  1997
+EFFN  3.911818
+CKSUM 3015610723
+GA 2.324 4.234
+TC 2.343 1.212
+NC 2.354 5.456
+STATS LOCAL MSV       -8.5786  0.71858
+STATS LOCAL VITERBI   -9.3632  0.71858
+STATS LOCAL FORWARD   -3.4823  0.71858
+HMM          A        C        G        T   
+            m->m     m->i     m->d     i->m     i->i     d->m     d->d
+  COMPO   1.24257  1.59430  1.62906  1.16413
+          1.38629  1.38629  1.38629  1.38629
+          0.03960  3.94183  3.94183  1.46634  0.26236  0.00000        *
+      1   2.69765  2.44396  2.81521  0.24089      1 t x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03960  3.94183  3.94183  1.46634  0.26236  1.09861  0.40547
+      2   2.72939  2.37873  2.85832  0.24244      2 t x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03725  4.00179  4.00179  1.46634  0.26236  1.09861  0.40547
+      3   0.16099  3.16370  2.87328  2.99734      3 a x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03604  4.03416  4.03416  1.46634  0.26236  1.09861  0.40547
+      4   1.98862  2.42132  0.42649  2.10770      4 g x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03539  4.05203  4.05203  1.46634  0.26236  1.09861  0.40547
+      5   1.96369  2.69532  0.36534  2.32099      5 g x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03764  4.06427  3.92372  1.46634  0.26236  1.09861  0.40547
+      6   2.56994  2.11239  2.71946  0.30571      6 t x - -
+          1.37159  1.41129  1.39124  1.37159
+          0.03806  3.89715  4.07214  1.50442  0.25122  1.00714  0.45454
+      7   2.58388  2.10353  2.64646  0.31253     12 t x - -
+          1.38764  1.38524  1.38764  1.38465
+          0.03494  4.03864  4.09125  1.40070  0.28293  1.09237  0.40860
+      8   2.18552  2.70201  0.28821  2.64645     14 g x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03628  4.09157  3.96779  1.46634  0.26236  1.09861  0.40547
+      9   2.16916  2.82142  0.28427  2.60854     15 g x - -
+          1.38091  1.39033  1.38365  1.39033
+          0.03566  4.00237  4.08886  1.38021  0.28972  1.01958  0.44745
+     10   2.45517  2.15232  2.42886  0.34277     18 t x - -
+          1.39065  1.39065  1.39065  1.37335
+          0.03536  4.01212  4.09576  1.39554  0.28462  1.09775  0.40589
+     11   2.10260  2.95484  0.28160  2.64222     21 g x - -
+          1.36740  1.40555  1.40555  1.36740
+          0.03843  3.92069  4.02468  1.44733  0.26814  1.09856  0.40549
+     12   2.54740  0.30185  2.61355  2.21647     26 c x - -
+          1.38748  1.38276  1.38748  1.38748
+          0.03457  4.05446  4.09623  1.40847  0.28040  1.05496  0.42803
+     13   0.28443  2.72003  2.32214  2.48149     28 a x - -
+          1.38740  1.38740  1.38298  1.38740
+          0.03441  4.05976  4.10001  1.41198  0.27926  1.09780  0.40587
+     14   0.29412  2.55413  2.49679  2.35701     30 a x - -
+          1.38194  1.39067  1.38194  1.39067
+          0.03505  4.02482  4.10005  1.39522  0.28473  1.09929  0.40512
+     15   0.18837  2.99710  2.82270  2.77556     33 a x - -
+          1.39015  1.39472  1.37503  1.38539
+          0.03725  3.97815  4.02618  1.37955  0.28994  1.10102  0.40426
+     16   0.50816  2.05151  2.22111  1.82407     37 a x - -
+          1.36727  1.38730  1.39683  1.39405
+          0.04830  3.89881  3.61610  1.29026  0.32186  1.05306  0.42905
+     17   2.11260  2.73141  0.29747  2.64152     41 g x - -
+          1.36913  1.40376  1.40376  1.36913
+          0.03705  3.93681  4.08299  1.44872  0.26771  1.07479  0.41759
+     18   2.24459  1.90539  2.34054  0.43234     46 t x - -
+          1.33632  1.42493  1.39937  1.38665
+          0.04427  3.64574  4.06297  1.70501  0.20061  1.21309  0.35279
+     19   0.44322  2.17202  2.18055  2.03175     57 a x - -
+          1.41047  1.41471  1.36338  1.35797
+          0.03970  3.81957  4.07540  1.65588  0.21186  1.22788  0.34660
+     20   0.33340  2.42691  2.40824  2.25160     66 a x - -
+          1.29389  1.44615  1.37917  1.43324
+          0.04223  3.70146  4.09459  1.55158  0.23815  1.05880  0.42598
+     21   2.50563  1.98543  2.69601  0.33746     74 t x - -
+          1.39462  1.39462  1.42862  1.32990
+          0.04184  3.80216  3.98177  1.80466  0.17976  1.00279  0.45705
+     22   2.54484  1.97505  2.66483  0.33806     84 t x - -
+          1.39134  1.39489  1.38662  1.37246
+          0.03877  3.97504  3.95038  1.37620  0.29107  1.13932  0.38572
+     23   2.10159  2.83856  0.29282  2.61635     88 g x - -
+          1.39682  1.39682  1.35536  1.39682
+          0.05046  3.75402  3.65808  1.08330  0.41321  1.13019  0.39004
+     24   2.25298  0.61854  2.50691  1.29221     90 c x - -
+          1.35803  1.49605  1.46737  1.24379
+          0.06091  3.28322  3.83564  1.89752  0.16245  1.28788  0.32276
+     25   1.27819  2.23285  0.76242  1.91259    106 g x - -
+          1.29024  1.67349  1.68279  1.04597
+          0.05752  3.44263  3.73311  2.58671  0.07825  1.26818  0.33037
+     26   1.86925  2.58352  0.39466  2.33986    131 g x - -
+          1.31084  1.49412  1.46666  1.29002
+          0.04698  3.54257  4.07715  2.25245  0.11109  0.86163  0.54900
+     27   2.38297  1.93394  2.39162  0.39800    151 t x - -
+          1.33582  1.47359  1.44163  1.30411
+          0.04951  3.48445  4.03783  2.15951  0.12260  1.21681  0.35122
+     28   2.41717  2.17810  2.62774  0.32113    170 t x - -
+          1.36805  1.48060  1.37439  1.32840
+          0.04849  3.50958  4.05014  2.58370  0.07850  1.22399  0.34822
+     29   2.57764  2.35132  2.56552  0.28512    194 t x - -
+          1.43829  1.43458  1.24787  1.43829
+          0.04667  3.56670  4.05428  2.49706  0.08591  1.23744  0.34267
+     30   2.47248  2.07688  2.62257  0.33172    215 t x - -
+          1.25120  1.52623  1.70635  1.15531
+          0.08932  3.31524  3.01336  2.81842  0.06156  1.22909  0.34610
+     31   2.25937  2.13157  2.02027  0.43957    248 t x - -
+          1.18172  1.43522  1.72841  1.28150
+          0.07936  2.93117  3.77395  2.46269  0.08906  0.60457  0.79034
+     32   2.04508  2.84981  0.30490  2.58263    280 g x - -
+          1.17665  1.66785  1.66218  1.16056
+          0.05998  3.23615  3.96853  2.83684  0.06040  1.01952  0.44749
+     33   2.45103  0.38098  2.56776  1.87147    317 c x - -
+          1.24153  1.52524  1.60663  1.22783
+          0.05538  3.39046  3.90294  2.73920  0.06680  1.18729  0.36391
+     34   2.22082  0.36258  2.75077  2.02704    347 c x - -
+          1.15008  1.62014  1.86511  1.10673
+          0.06086  3.18178  4.04341  2.94504  0.05403  1.25991  0.33363
+     35   0.27033  2.66664  2.52541  2.43767    388 a x - -
+          1.24951  1.47565  1.41392  1.42074
+          0.07123  3.00373  3.95552  3.13655  0.04440  1.28173  0.32512
+     36   2.83107  2.41670  2.97197  0.22235    439 t x - -
+          1.37071  1.57683  1.38637  1.23972
+          0.05293  3.45216  3.91807  2.54402  0.08181  1.14651  0.38235
+     37   2.52322  2.25084  2.45909  0.31611    465 t x - -
+          1.26335  1.55077  1.59008  1.19965
+          0.07504  3.13329  3.55006  3.08962  0.04659  1.13108  0.38962
+     38   0.45807  2.30687  1.98940  2.03143    512 a x - -
+          1.15472  1.67511  1.53797  1.26320
+          0.09820  3.13076  2.99876  2.79197  0.06326  1.39915  0.28343
+     39   2.37471  0.42180  2.44763  1.80427    550 c x - -
+          1.23785  1.49058  1.48364  1.35502
+          0.06081  3.19472  4.01643  2.41851  0.09327  0.94671  0.49105
+     40   2.32826  1.95481  2.36781  0.40458    578 t x - -
+          1.36586  1.46001  1.43000  1.29720
+          0.05257  3.39673  4.03256  1.84862  0.17133  1.40979  0.27997
+     41   2.68669  2.13935  2.81520  0.28200    592 t x - -
+          1.34965  1.42793  1.45781  1.31633
+          0.04735  3.57826  3.99988  2.09424  0.13144  1.22129  0.34934
+     42   2.55904  2.16444  2.70859  0.29952    609 t x - -
+          1.12072  1.61936  1.63578  1.26895
+          0.07346  3.25910  3.42962  2.85641  0.05919  1.38363  0.28857
+     43   1.99923  1.61027  2.26343  0.57851    646 t x - -
+          1.32290  1.58747  1.61095  1.11018
+          0.06656  3.08568  3.97944  2.44774  0.09046  0.75593  0.63407
+     44   0.23887  2.79899  2.55209  2.60783    675 a x - -
+          1.18557  1.50323  1.59070  1.31590
+          0.05597  3.38637  3.88222  2.46900  0.08847  1.27945  0.32599
+     45   0.29593  2.53488  2.53903  2.32335    701 a x - -
+          1.08710  1.54222  1.59276  1.40430
+          0.07539  2.94521  3.91062  1.91623  0.15918  1.22327  0.34852
+     46   2.58352  2.40524  2.76700  0.25955    725 t x - -
+          1.19685  1.58503  1.74852  1.14293
+          0.06124  3.18279  4.02089  2.82961  0.06085  1.05474  0.42814
+     47   2.13251  2.88788  0.29508  2.50964    764 g x - -
+          1.20891  1.55463  1.68206  1.19000
+          0.06526  3.12574  3.94910  2.41448  0.09367  1.10396  0.40280
+     48   2.23841  2.99164  0.25118  2.72900    792 g x - -
+          1.26330  1.55339  1.52606  1.24355
+          0.05464  3.34968  4.01313  2.78872  0.06347  1.15133  0.38012
+     49   2.57533  0.32900  2.64632  2.01501    824 c x - -
+          1.35118  1.39828  1.40141  1.39516
+          0.04340  3.79297  3.91506  1.59549  0.22666  1.20075  0.35806
+     50   0.46433  2.04127  2.23437  2.00605    833 a x - -
+          1.23062  1.36903  1.62282  1.36182
+          0.05764  3.31530  3.92762  2.28791  0.10700  1.07910  0.41536
+     51   0.27513  2.77017  2.28518  2.57549    853 a x - -
+          1.27958  1.58726  1.46109  1.25394
+          0.05750  3.30072  3.96214  2.60776  0.07656  1.25708  0.33475
+     52   0.20149  2.86434  2.84551  2.69770    883 a x - -
+          1.23645  1.62259  1.71174  1.10368
+          0.05756  3.26729  4.02702  2.54508  0.08172  1.27391  0.32814
+     53   0.26982  2.65833  2.50477  2.46835    911 a x - -
+          1.36005  1.50358  1.48100  1.22550
+          0.06921  3.37553  3.42118  2.36646  0.09851  1.27560  0.32748
+     54   0.40022  2.19284  2.22687  2.20396    934 a x - -
+          1.12070  1.60472  1.53213  1.35895
+          0.05523  3.36752  3.94966  2.42917  0.09224  0.84774  0.55928
+     55   2.11356  0.46400  2.46442  1.79955    960 c x - -
+          1.23932  1.35913  1.50478  1.46331
+          0.05187  3.47055  3.94022  2.35854  0.09933  1.12102  0.39445
+     56   1.85868  0.79440  2.22069  1.25971    983 c x - -
+          1.21951  1.50212  1.51138  1.34185
+          0.06404  3.29054  3.69705  1.75742  0.18933  1.18410  0.36532
+     57   1.33272  2.32720  0.71452  1.90215    999 g x - -
+          1.12229  1.49343  1.56653  1.42255
+          0.04920  3.46654  4.08749  2.17995  0.11996  1.31769  0.31164
+     58   2.48337  0.43652  2.46331  1.68683   1017 c x - -
+          1.34704  1.55461  1.38112  1.28222
+          0.04823  3.61532  3.90311  2.20911  0.11631  1.00864  0.45368
+     59   0.41659  2.44509  1.93972  2.20507   1034 a x - -
+          1.38198  1.38198  1.39194  1.38932
+          0.03641  3.98130  4.06929  1.35873  0.29704  1.31330  0.31325
+     60   0.41612  2.39160  1.97116  2.21075   1037 a x - -
+          1.03649  1.46430  1.57421  1.57557
+          0.04769  3.52580  4.06641  2.32461  0.10294  0.84329  0.56263
+     61   2.66264  2.12302  2.82746  0.28581   1056 t x - -
+          1.36925  1.39635  1.38930  1.39048
+          0.04097  3.97400  3.84718  1.39433  0.28502  1.12205  0.39395
+     62   2.26510  2.13196  2.42551  0.37231   1060 t x - -
+          1.37965  1.39147  1.39147  1.38264
+          0.04082  3.91610  3.90805  1.24613  0.33914  0.95192  0.48776
+     63   0.41244  2.25761  2.16787  2.12907   1062 a x - -
+          1.34515  1.41203  1.41203  1.37753
+          0.04054  3.77835  4.08203  1.30483  0.31638  1.11819  0.39582
+     64   2.51464  0.37905  2.62296  1.82008   1068 c x - -
+          1.39543  1.38753  1.39233  1.37008
+          0.03854  3.90584  4.03535  1.36573  0.29463  1.13682  0.38689
+     65   2.16380  2.11332  2.18714  0.42765   1073 t x - -
+          1.38764  1.38471  1.38519  1.38764
+          0.03575  4.05376  4.03073  1.40080  0.28289  1.03825  0.43707
+     66   2.79349  2.39141  2.87271  0.23478   1075 t x - -
+          1.37227  1.39101  1.39101  1.39101
+          0.03597  4.01447  4.05827  1.39017  0.28639  1.06429  0.42308
+     67   2.82488  2.47749  2.93179  0.21887   1078 t x - -
+          1.38141  1.39112  1.38915  1.38353
+          0.03661  3.99477  4.04370  1.35958  0.29675  1.13439  0.38804
+     68   2.77679  2.30433  2.90694  0.24425   1081 t x - -
+          1.37593  1.38989  1.45520  1.32825
+          0.04447  3.68736  3.99242  1.76176  0.18843  0.98580  0.46703
+     69   2.47698  3.17398  0.19595  2.95437   1093 g x - -
+          1.38264  1.38264  1.39734  1.38264
+          0.05358  3.96553  3.40487  1.40348  0.28202  1.03112  0.44100
+     70   2.84327  0.27906  2.97336  2.00890   1097 c x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03412  4.08811  4.08811  1.46634  0.26236  0.69006  0.69625
+     71   0.21870  2.83638  2.69251  2.65798   1098 a x - -
+          1.37446  1.37942  1.39640  1.39509
+          0.03670  3.93983  4.09935  1.41905  0.27700  1.10002  0.40476
+     72   2.35233  0.46085  2.23804  1.78715   1103 c x - -
+          1.38536  1.38781  1.38781  1.38421
+          0.03493  4.03822  4.09272  1.39310  0.28542  1.09638  0.40658
+     73   2.57111  0.32543  2.74124  1.98892   1105 c x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03381  4.09688  4.09688  1.46634  0.26236  1.09626  0.40664
+     74   0.27014  2.61416  2.53262  2.47636   1106 a x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03461  4.09267  4.05587  1.46634  0.26236  1.09748  0.40603
+     75   0.52873  2.16549  1.91736  1.90409   1107 a x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03426  4.08396  4.08396  1.46634  0.26236  1.07423  0.41788
+     76   2.33134  0.38082  2.65861  1.90055   1108 c x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03466  4.07266  4.07266  1.46634  0.26236  1.09861  0.40547
+     77   2.20588  0.45134  2.35553  1.84373   1109 c x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03550  4.04912  4.04912  1.46634  0.26236  1.09861  0.40547
+     78   2.69018  2.22054  2.82311  0.26898   1110 t x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.03711  4.00561  4.00561  1.46634  0.26236  1.09861  0.40547
+     79   0.16248  3.15867  2.86159  2.98963   1111 a x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.04048  3.92018  3.92018  1.46634  0.26236  1.09861  0.40547
+     80   0.17484  3.04770  2.86638  2.88183   1112 a x - -
+          1.38629  1.38629  1.38629  1.38629
+          0.02045  3.90014        *  1.46634  0.26236  0.00000        *
+//
diff --git a/test/jalview/io/test_PKinase_hmm.txt b/test/jalview/io/test_PKinase_hmm.txt
new file mode 100644 (file)
index 0000000..e1ad9f9
--- /dev/null
@@ -0,0 +1,806 @@
+HMMER3/e [3.0 | March 2010]
+NAME  Pkinase
+ACC   PF00069.17
+DESC  Protein kinase domain
+LENG  260
+ALPH  amino
+RF    no
+CONS  yes
+CS    yes
+MAP   yes
+DATE  Thu Jun 16 11:44:06 2011
+NSEQ  54
+EFFN  3.358521
+CKSUM 3106786190
+GA    70.30 70.30
+TC    70.30 70.30
+NC    70.20 70.20
+STATS LOCAL MSV      -10.7215  0.70254
+STATS LOCAL VITERBI  -11.6541  0.70254
+STATS LOCAL FORWARD   -5.2305  0.70254
+HMM          A        C        D        E        F        G        H        I        K        L        M        N        P        Q        R        S        T        V        W        Y   
+            m->m     m->i     m->d     i->m     i->i     d->m     d->d
+  COMPO   2.60017  4.19886  2.94089  2.63789  3.35087  2.89119  3.48337  2.79435  2.60265  2.43454  3.62613  3.06133  3.41286  3.09693  2.94507  2.65650  2.87761  2.67871  4.54052  3.43274
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.00000        *
+      1   2.91704  4.31028  4.76351  3.63148  2.10912  3.47710  4.39734  2.27639  3.96619  1.99282  3.42844  4.19567  4.43771  4.11903  3.67403  3.22736  3.14918  2.35905  3.32515  1.82622      1 y - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+      2   2.77204  4.20708  3.06476  1.97968  4.66603  3.66509  3.19858  3.37903  2.25347  3.34018  4.38833  2.97180  4.05804  2.36838  2.43173  2.67542  2.50268  2.83403  5.78758  4.38976      2 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+      3   2.90076  4.04294  3.31590  2.80413  3.08157  3.87481  4.12616  2.18958  2.49735  1.97194  3.73714  3.32717  3.98753  3.23115  3.12315  2.99137  2.62008  2.29426  5.21478  3.75979      3 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+      4   2.89383  4.85429  3.10311  2.63174  3.71383  2.56808  3.47232  2.82076  2.61844  1.98342  3.72320  3.05498  4.17347  3.05527  3.32194  2.85608  2.93671  2.18878  5.40057  3.87183      4 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+      5   2.68261  5.39185  2.80437  1.87471  4.73638  2.79887  3.69591  4.22191  2.19487  3.69685  4.08896  3.12413  3.70490  2.48424  2.08916  2.53260  3.02309  3.43812  5.82480  4.41426      5 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+      6   2.77253  4.06085  3.07881  2.53373  4.10647  3.71564  3.68370  2.64290  2.00036  2.72968  4.17370  3.24239  3.08607  2.77632  2.72820  2.69921  2.54335  2.71931  5.60386  4.26496      6 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+      7   3.42930  4.74416  5.34765  4.76823  3.71832  4.71430  5.09461  1.33015  3.54417  1.12594  3.33523  4.84641  5.00427  4.73010  4.64986  4.05097  3.66327  1.83083  5.51142  4.37013      7 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+      8   2.57460  4.94286  4.00732  3.93216  5.40516  0.41612  5.15134  4.86315  4.18766  4.52736  5.33508  4.05990  4.45245  3.74651  4.46171  3.15888  3.14590  4.15180  6.71159  5.52767      8 G - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+      9   2.30218  5.38172  3.03799  2.02026  4.18991  3.65799  3.84554  3.67215  2.28945  3.68495  4.42365  2.84227  3.73039  2.44555  2.39428  2.00278  2.95859  3.63127  5.81726  4.40923      9 s - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     10   4.54226  6.07621  5.39207  5.44513  6.34643  0.07137  6.34600  6.33790  5.73770  5.76452  6.83374  5.56171  5.46536  5.98137  5.73783  4.76037  5.08470  5.67502  7.03864  6.52156     10 G - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     11   2.06444  5.37337  2.91595  2.40063  4.70969  2.61181  3.84889  4.18948  2.46835  3.67503  4.41668  2.62917  4.05392  2.88235  2.66711  2.00495  2.47288  3.39649  5.81159  4.40596     11 s - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     12   2.90920  4.46494  4.12493  3.14570  1.52027  3.22992  4.24969  2.92840  3.46467  2.66529  3.12827  3.55640  4.33979  3.72214  3.72236  2.53517  2.98442  2.55125  5.06498  2.30159     12 f - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     13   2.21104  4.80722  4.64199  4.55509  5.54982  0.52550  5.49025  5.04875  4.70671  4.72740  5.47955  4.30215  4.43233  4.84666  4.86038  1.95116  3.45005  4.17507  6.87595  5.79039     13 G - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     14   2.71551  3.46186  3.01248  2.27453  4.55840  3.55853  3.50842  3.55064  2.03335  3.34882  4.31847  3.17065  4.07218  2.83960  2.83653  2.25762  2.26864  2.61469  5.72841  4.35037     14 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     15   3.17885  3.97005  5.63014  5.16553  4.35293  4.89782  5.77682  2.09398  5.06494  2.94083  4.14496  5.20428  5.30924  5.30763  5.20260  4.32158  3.61414  0.44769  6.26043  5.04118     15 V - - E
+          2.68625  4.42232  2.77526  2.73102  3.46361  2.40519  3.72501  3.29361  2.67747  2.69306  4.24696  2.90353  2.73746  3.18153  2.89807  2.37893  2.77526  2.98499  4.58484  3.61510
+          0.09563  2.43065  5.73865  0.67073  0.71608  0.48576  0.95510
+     16   2.91101  3.31342  4.36759  3.41772  2.45121  4.01227  4.31421  2.75922  2.81772  2.31733  3.50420  3.69862  4.38187  3.88257  3.14725  3.02772  3.14303  2.46483  3.37889  1.69905     18 y - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     17   2.88484  5.28431  3.03179  2.31849  4.58595  3.47769  3.54625  2.98124  1.69233  2.43413  4.04064  3.16353  4.06907  2.72555  2.58277  2.55274  3.04512  3.20501  5.74377  4.36100     19 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     18   1.57125  2.56460  3.38436  3.39201  3.66458  2.34190  4.20526  2.93932  3.32823  2.44127  3.26099  3.74334  4.30466  3.60817  3.63469  3.01628  2.92537  2.55308  5.13581  3.91882     20 a - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     19   2.89298  4.40558  3.44708  2.63051  3.77015  3.77747  2.87940  2.57515  2.33949  2.85128  3.20054  3.37379  4.16367  2.65910  2.52913  2.67954  2.59930  2.46709  5.42679  3.74337     21 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     20   2.88350  5.37811  2.42858  2.28192  4.71668  3.65945  2.35349  4.19788  2.20596  2.91798  4.42054  2.38258  4.05280  2.81490  2.60119  2.77457  3.11461  3.76528  3.43428  3.80493     22 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     21   2.59359  5.30144  3.00667  2.46268  4.60954  3.67285  3.22394  2.91749  2.13087  2.60378  4.35201  3.05590  3.51881  2.48537  2.35096  2.62551  3.00998  2.84793  5.75687  4.36947     23 k - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     22   2.64500  5.38003  2.46961  2.36386  4.71962  2.36153  3.71093  3.77963  2.19342  3.27291  4.42213  2.49968  3.44456  2.94396  2.94770  2.23767  2.90215  3.58800  5.81601  3.79868     24 k - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     23   2.71410  5.35453  2.26257  2.17828  4.68327  3.06138  3.85215  3.65600  2.51871  3.65284  4.39957  2.64619  4.05631  2.95399  2.98284  2.41102  1.94961  3.19379  5.79713  3.78693     25 t - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03260  5.01631  3.67114  0.61958  0.77255  0.48576  0.95510
+     24   2.77509  4.50579  3.06414  2.40741  4.68877  2.10468  3.84020  4.16638  2.52713  3.65577  4.39945  2.31826  2.82304  2.55347  2.45557  2.51717  3.10489  3.55245  5.79545  3.68618     26 g - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.13496  4.99383  2.12471  0.61958  0.77255  0.54753  0.86365
+     25   2.82390  4.23357  2.59579  2.09029  4.65095  3.47120  3.53571  3.50264  1.93281  3.24335  4.10745  2.98984  3.99409  2.41262  2.43858  2.60001  2.84781  3.57090  5.75206  3.98239     27 k - - E
+          2.68634  4.42166  2.77510  2.73101  3.46370  2.40521  3.72473  3.29370  2.67713  2.69347  4.24706  2.90350  2.73742  3.18145  2.89817  2.37895  2.77536  2.98516  4.58493  3.61485
+          0.21086  2.33296  2.37401  1.37928  0.29003  0.81455  0.58490
+     26   2.79249  4.86773  3.27912  2.48247  3.81836  3.65430  3.86742  2.36980  2.31612  2.40000  3.66176  2.98804  3.52938  2.45192  2.80383  2.80149  2.71760  2.93241  5.39419  3.83742     36 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01259  4.77670  5.49905  0.61958  0.77255  0.27298  1.43175
+     27   2.94684  4.40681  4.93000  4.33270  2.14562  4.19543  4.43742  2.60780  4.12995  2.51432  3.32273  4.32339  4.55150  4.25562  4.15094  3.50804  3.26683  1.12964  4.39266  2.23526     37 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     28   0.67405  4.13502  4.78133  4.26234  4.00859  4.13420  4.88775  2.58668  4.14876  2.87877  3.59530  4.37511  4.66004  4.38446  4.34251  3.50924  3.44597  2.20111  5.62436  4.43519     38 A - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     29   2.77559  4.05359  4.82280  4.21814  3.45081  3.88127  4.46447  1.69887  3.29990  2.06046  2.92956  4.25618  4.49083  4.18293  4.07725  3.28739  3.19210  1.31639  4.98894  3.80930     39 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     30   4.13385  6.06880  4.58555  3.84767  5.73274  4.53840  4.41573  5.06650  0.32256  4.37802  5.30885  4.14872  4.92009  3.55775  2.54913  4.11741  4.25754  4.75872  6.25921  5.22828     40 K - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     31   2.53136  3.93442  3.55191  2.54113  3.59001  3.81267  3.67691  2.09853  2.22431  2.85063  3.63116  3.45300  4.19661  2.87681  2.71089  2.96116  2.67441  2.46338  5.34241  3.76111     41 i - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     32   2.80227  4.30542  4.81704  3.71619  2.31247  3.45194  4.41496  1.85614  4.00698  1.68898  3.06826  4.22398  4.44809  4.15126  4.03957  3.11345  3.01936  1.82478  4.92889  3.75130     42 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     33   2.72320  4.19698  2.89173  2.30854  4.21536  3.66470  3.63903  3.54937  1.81020  3.33297  4.38970  2.50126  3.12497  2.85129  2.61476  2.47307  2.93549  3.43057  4.63863  3.86554     43 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     34   2.73748  5.16363  3.24304  2.62749  4.42406  3.39882  3.64889  3.08793  1.75481  2.64054  4.22767  2.81684  3.49630  2.92572  2.69253  2.71691  2.78362  2.91622  5.65055  3.09244     44 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     35   2.82342  4.21564  2.57688  2.18304  4.09635  3.66104  3.29269  4.17416  2.24176  3.24419  4.40775  3.13331  3.02670  2.66210  2.30119  2.38622  2.91913  2.84969  5.80393  4.13733     45 e - - H
+          2.68618  4.42225  2.77520  2.73124  3.46354  2.40513  3.72495  3.29354  2.67741  2.69355  4.24690  2.90347  2.73731  3.18147  2.89801  2.37887  2.77520  2.98519  4.58477  3.61503
+          0.02362  3.90596  5.73865  0.48782  0.95182  0.48576  0.95510
+     36   2.81479  5.38805  2.34307  2.08229  3.84722  3.00939  3.24618  4.21561  2.24819  3.24444  4.42924  2.80965  3.63231  2.74299  2.65208  2.41080  2.72103  3.26063  5.82196  4.16400     47 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     37   2.42659  5.32934  2.94543  1.98753  4.27035  3.66735  3.85733  2.97282  2.27697  3.20526  3.75542  2.69174  3.50027  2.79550  2.45131  2.66535  2.70832  3.28701  5.77800  4.07668     48 e - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     38   2.82479  5.36482  2.46403  2.36491  4.23121  3.19666  3.53460  3.47934  2.01766  2.87145  4.06028  2.53791  3.88358  2.73438  2.79605  2.39315  2.94316  3.30320  5.80464  3.67777     49 k - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     39   2.81259  3.82036  2.58997  2.16257  3.93187  3.50795  3.44913  3.32347  2.23760  3.42042  3.43188  3.03914  3.18139  2.98833  2.90722  1.97318  3.04237  3.44327  4.85883  4.01646     50 s - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.04017  5.01631  3.41907  0.61958  0.77255  0.48576  0.95510
+     40   2.75150  4.68420  2.78864  2.20581  3.96394  3.14028  3.85474  3.62649  2.17804  2.84544  3.93254  2.66146  3.79370  2.72658  2.87564  2.43841  2.71937  3.23202  3.36778  4.34996     51 k - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01020  4.98634  5.70869  0.61958  0.77255  0.56699  0.83755
+     41   2.52028  4.29421  2.93844  2.26593  3.28616  3.42961  3.89113  3.40312  1.92589  2.89626  3.59280  3.04537  4.08209  2.42956  3.02333  2.89065  2.87512  2.78376  5.62895  3.97726     52 k - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.06456  4.98634  2.88790  0.61958  0.77255  0.56699  0.83755
+     42   2.52102  4.66200  2.60886  2.12080  3.90563  3.43164  3.41299  3.76759  2.19798  2.95231  4.37667  2.71584  3.31098  2.66775  2.46389  2.65499  2.89357  3.57073  4.74853  4.36793     53 e - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.06881  4.93254  2.82535  0.61958  0.77255  0.69302  0.69327
+     43   2.65676  5.27743  2.81592  2.16715  4.59834  3.44096  3.79920  2.82354  2.10889  3.57233  3.78816  2.93522  4.00237  2.20078  2.58862  2.72374  2.99283  3.18643  5.72482  3.30249     54 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.04191  4.87514  3.39892  0.61958  0.77255  0.80592  0.59181
+     44   2.46416  5.14935  3.14274  2.35064  4.42785  3.46788  3.62138  3.06885  2.39724  2.90472  4.00413  2.77252  4.01153  2.56699  2.69346  2.37713  2.33258  3.34725  5.62407  3.30627     55 t - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.15381  4.84499  2.00472  0.61958  0.77255  0.85820  0.55151
+     45   2.15178  5.11690  2.80767  2.47016  4.06926  3.56450  3.25874  3.42510  2.38373  2.72748  4.17388  2.58132  3.95629  2.68997  2.59104  2.52019  2.89357  3.10461  5.58730  3.84420     56 a - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.06869  4.70471  2.85898  0.61958  0.77255  1.05523  0.42788
+     46   2.33893  4.38200  3.78128  3.08857  2.87706  3.76539  4.03303  2.50172  2.82237  2.26545  3.48958  3.56901  4.14175  3.13269  2.43377  3.02211  2.55318  2.18677  4.40164  3.75633     57 v - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.07407  4.65033  2.78326  0.61958  0.77255  1.03937  0.43646
+     47   2.66580  4.77769  3.25859  2.69691  3.69577  3.61140  3.56963  3.36841  2.45062  2.28390  3.86113  2.83101  3.99793  3.01640  2.00932  2.40384  2.97180  2.98514  3.81809  4.01106     58 r - - H
+          2.68588  4.42292  2.77574  2.73101  3.46421  2.40561  3.72562  3.29362  2.67747  2.69305  4.24679  2.90348  2.73776  3.18179  2.89693  2.37874  2.77432  2.98554  4.58544  3.61510
+          0.56084  0.85690  5.33966  1.67148  0.20822  0.22069  1.61932
+     48   3.87852  6.35819  2.88185  0.33512  5.75300  3.98086  4.66680  5.41085  3.73193  4.87592  5.81368  3.19190  4.67406  3.86930  4.28895  3.74624  4.21685  4.94226  6.88673  5.40485     78 E - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     49   2.34469  4.06185  4.67394  3.74635  3.19070  3.72385  4.38165  1.69529  3.89930  1.68521  3.30505  3.88179  4.42519  3.50953  3.71087  3.12279  3.14596  1.99339  4.94125  3.41486     79 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     50   2.41611  3.92039  3.06862  2.24055  4.69692  3.38839  3.50460  4.17440  2.17094  3.43336  4.01855  2.84870  4.05421  2.22409  2.42800  2.49697  2.93959  3.48161  5.80403  3.10747     80 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     51   2.65097  4.31309  4.79937  4.19096  3.25102  4.08746  4.41763  1.57396  3.99634  1.77576  3.18772  3.58572  4.45127  4.14513  4.03729  2.91921  3.15786  1.73265  4.93848  3.33785     81 i - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     52   2.71474  4.35776  4.49839  3.90546  3.26558  3.60358  3.11363  2.58541  3.76519  1.24138  2.56017  3.78382  4.40165  3.77674  3.90460  2.91080  2.88501  2.43218  4.97232  3.44306     82 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     53   2.21717  5.37509  3.13954  2.36108  4.71254  3.44569  3.50643  4.19289  1.90576  2.89362  4.41783  2.84264  3.50886  2.51670  2.27883  2.73413  2.79427  3.37900  5.81221  4.40629     83 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     54   2.88332  4.76187  3.15794  2.34306  4.64959  3.18467  2.98724  4.11774  2.20976  2.84622  3.53657  2.69640  4.06011  2.81953  2.22587  2.26090  2.67755  3.39248  5.77872  3.89328     84 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     55   2.92075  3.71086  4.82119  4.21031  2.91851  4.08375  4.41406  2.48059  4.00923  1.14255  2.77088  4.22517  4.44739  4.15194  3.51737  2.79440  3.04088  2.14784  4.92583  3.58797     85 l - - H
+          2.68619  4.42231  2.77526  2.73130  3.46360  2.40505  3.72501  3.29360  2.67737  2.69361  4.24696  2.90322  2.73746  3.18153  2.89797  2.37878  2.77526  2.98514  4.58483  3.61509
+          0.21093  1.81438  3.60337  0.15203  1.95873  0.48576  0.95510
+     56   2.87228  4.32697  2.43695  2.52023  4.72535  3.09966  3.42727  4.21076  2.24746  3.68599  4.14994  2.21640  3.70120  2.45856  2.42604  2.20075  2.84715  3.77128  5.81417  4.40372     87 s - - S
+          2.68626  4.42233  2.77498  2.73131  3.46362  2.40515  3.72479  3.29362  2.67733  2.69363  4.24698  2.90355  2.73719  3.18141  2.89809  2.37895  2.77498  2.98527  4.58485  3.61511
+          0.08622  2.53438  5.71435  0.90816  0.51628  0.44628  1.02166
+     57   2.95437  4.05540  4.02453  3.66262  4.73022  3.00582  0.63840  4.27369  3.61156  3.92435  4.76053  3.90244  4.38221  3.97389  3.93213  2.36608  3.39859  3.79517  6.08861  4.80370     91 H - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     58   2.74925  4.59154  2.64384  2.02057  4.69046  3.19970  3.85151  4.16644  2.39568  3.65893  3.99620  3.06676  1.73396  2.95270  2.98758  2.52836  2.96698  3.57815  5.80119  4.39902     92 p - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     59   2.77600  3.63123  3.60742  3.04389  2.88763  3.83093  3.22852  3.27052  2.82124  2.96220  3.83761  1.44485  4.21384  3.33393  3.26463  3.06163  2.84916  2.86372  5.30436  2.85576     93 n - - S
+          2.68619  4.42226  2.77521  2.73125  3.46355  2.40506  3.72496  3.29355  2.67742  2.69356  4.24691  2.90348  2.73741  3.18148  2.89802  2.37880  2.77521  2.98520  4.58478  3.61504
+          0.02736  3.73933  5.73865  0.64347  0.74542  0.48576  0.95510
+     60   3.43736  4.73250  5.40681  4.85032  3.21534  3.89737  5.21348  0.72821  4.70181  2.29095  3.77438  4.92025  5.08011  4.86610  4.77171  4.12622  3.68020  1.72131  5.65218  4.46593     96 i - - B
+          2.68620  4.42119  2.77522  2.73126  3.46356  2.40515  3.72497  3.29356  2.67743  2.69357  4.24692  2.90349  2.73742  3.18149  2.89780  2.37889  2.77522  2.98521  4.58479  3.61505
+          0.04171  3.27988  5.73865  0.65380  0.73410  0.48576  0.95510
+     61   3.22247  3.52386  5.20134  4.62057  3.74032  4.49428  4.89197  1.38422  4.44333  2.03444  3.40884  4.64781  4.83078  4.60265  4.48778  3.55308  3.01459  1.16992  5.37248  4.18666     99 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     62   2.72238  4.59459  3.13585  2.30027  4.72566  3.17722  3.67251  4.20868  2.00822  3.53187  4.42604  2.97500  3.44674  2.41134  2.06447  2.53711  2.32763  3.77297  5.81907  4.41084    100 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     63   2.75790  4.02501  4.89076  4.27684  2.25991  4.10991  4.44304  2.31340  4.06541  1.38378  2.56521  4.26823  4.47075  4.19670  4.07763  3.42134  2.72551  2.21249  4.93572  3.01728    101 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     64   2.79378  4.36122  4.48297  3.70404  2.84684  4.03133  3.55103  1.94759  2.82835  1.82248  3.32801  4.05424  4.39941  3.70850  3.13439  3.15759  3.14407  2.41334  4.25902  2.30786    102 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     65   2.47264  4.33075  2.07830  2.03157  4.71750  2.27093  3.18950  4.19892  2.58523  3.68152  4.42156  3.04070  4.05295  2.84140  2.67254  2.59104  3.11515  3.76615  5.81569  3.60292    103 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     66   2.10377  4.03530  4.82986  4.21790  2.76136  4.07923  4.41023  2.08081  4.01359  2.30827  2.78821  4.22543  4.44340  4.15406  4.03913  2.38166  2.60707  1.97272  3.19782  3.33258    104 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     67   2.82605  3.67894  3.38070  3.01266  1.82001  3.97118  3.82789  2.76491  3.48734  2.34143  3.24926  3.10725  3.78017  3.42990  3.73647  2.98277  3.13977  2.32864  3.87637  2.72935    105 f - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.04987  5.01631  3.16967  0.61958  0.77255  0.48576  0.95510
+     68   2.55964  4.21441  3.10666  1.94329  4.49707  3.21758  3.46239  3.37098  2.39709  3.00488  3.51821  3.06808  4.06187  2.54621  2.66989  2.75991  2.68522  3.13970  5.68635  3.14043    106 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02094  4.97674  4.28127  0.61958  0.77255  0.42506  1.06054
+     69   2.80310  5.38415  2.22807  2.18295  4.72718  3.65266  3.36574  4.21171  2.46641  3.56699  4.42536  2.57848  3.46451  2.86899  2.36310  2.58224  2.17995  3.52075  5.81804  3.65548    107 t - - E
+          2.68640  4.42162  2.77535  2.73147  3.46354  2.40551  3.72458  3.29233  2.67716  2.69348  4.24762  2.90375  2.73699  3.18187  2.89837  2.37858  2.77480  2.98522  4.58549  3.61548
+          0.36809  1.18844  5.72853  1.68950  0.20409  0.46837  0.98355
+     70   2.88244  5.39287  2.47300  2.29715  3.79460  2.82884  3.28660  4.22374  2.09832  3.69810  4.43357  2.45444  3.07035  2.85151  2.47539  2.34133  3.01376  3.78345  5.82560  4.10620    126 k - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     71   2.57798  5.39101  2.06614  2.42374  4.73510  2.82383  3.84381  4.22040  2.28304  3.69587  4.43195  2.62257  3.38372  2.71683  2.73886  2.29050  2.66881  3.34289  5.82427  4.18691    127 d - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     72   2.58231  5.35788  2.77781  2.22432  4.08337  3.66211  2.49021  4.16401  2.37240  3.16748  4.40241  2.52484  4.05523  2.76334  2.63486  2.49164  2.89823  3.30761  4.95167  3.05734    128 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     73   2.78575  3.74303  4.78141  4.17260  2.95491  4.07322  4.40160  1.89067  3.97854  1.60353  2.95383  3.71592  3.11906  4.12798  3.50390  3.07790  2.85145  2.24111  4.92509  2.91282    129 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     74   2.58399  2.76389  4.59675  3.99881  3.19843  4.04871  3.62339  2.65148  3.84111  2.12752  3.45456  3.62454  3.46238  4.02369  3.94739  2.79096  3.14543  2.42948  3.13888  1.74690    130 y - - E
+          2.68624  4.42096  2.77500  2.73129  3.46360  2.40508  3.72501  3.29360  2.67747  2.69353  4.24696  2.90343  2.73746  3.18153  2.89807  2.37893  2.77510  2.98525  4.58483  3.61509
+          0.10354  2.49668  4.13492  0.66960  0.71726  0.48576  0.95510
+     75   3.07392  4.44555  4.97084  3.81418  2.87255  4.25097  4.57886  1.74564  4.16653  1.31678  2.12605  4.39109  4.59167  3.71495  4.19337  3.56380  3.30386  2.29390  5.05348  3.89648    133 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01003  5.00344  5.72579  0.61958  0.77255  0.52175  0.90012
+     76   2.86449  3.41378  5.01300  4.41506  3.07458  4.28568  4.64425  1.49634  4.22335  2.27773  3.54368  4.43380  4.63588  3.70581  4.25773  3.60458  3.30826  1.19505  5.13861  3.95920    134 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01003  5.00344  5.72579  0.61958  0.77255  0.46390  0.99109
+     77   2.91733  4.35063  4.55668  3.96112  2.40516  4.04680  4.36140  2.56068  3.81048  1.70108  1.79340  3.59899  4.41359  3.09405  3.93172  3.15547  2.48177  2.59902  4.96582  3.78095    135 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     78   2.76564  5.57030  2.50020  1.03018  4.90220  3.70297  3.44513  4.39514  2.75995  3.87044  4.62325  3.16505  3.19754  2.75935  3.27129  2.65802  3.28146  3.95557  6.00401  4.57374    136 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     79   2.81579  3.90369  4.68991  4.08721  2.27644  4.06399  3.63829  2.69790  3.58050  1.84024  3.31248  4.16081  4.42953  4.07816  3.60709  3.36667  3.01039  2.57256  4.40465  1.54393    137 y - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     80   2.45920  2.17262  4.69646  4.09287  3.22405  3.32199  3.21264  2.59887  3.91610  2.06244  2.25581  4.16309  3.61702  4.08102  3.98811  3.14866  3.14614  2.03766  4.93767  3.46778    138 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.04171  5.01631  3.37486  0.61958  0.77255  0.48576  0.95510
+     81   2.70314  5.37371  2.37994  1.91497  4.71601  2.93053  3.83161  4.20005  2.46492  3.55263  3.57885  2.58870  2.59223  2.74552  2.71928  2.69862  3.03649  3.29150  5.80804  4.39872    139 e - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01022  4.98481  5.70716  0.61958  0.77255  0.57090  0.83245
+     82   2.41993  3.72287  3.12898  2.52046  4.44831  1.89639  3.49536  3.62837  2.38762  3.31281  3.53904  2.44913  3.42379  3.00780  3.12891  2.87912  2.75467  3.52812  5.65946  3.81984    140 g - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.10979  4.98481  2.33166  0.61958  0.77255  0.57090  0.83245
+     83   2.77350  5.21303  2.43943  2.62703  4.54309  1.39496  3.89257  3.99092  2.60267  3.54085  4.32260  3.04209  4.06226  3.01831  3.03242  2.64588  2.77651  3.04353  5.73236  4.35922    141 g - - -
+          2.68631  4.42210  2.77537  2.73126  3.46359  2.40522  3.72475  3.29338  2.67758  2.69250  4.24657  2.90377  2.73770  3.18148  2.89796  2.37902  2.77541  2.98478  4.58507  3.61496
+          0.21230  1.67338  5.60865  1.39945  0.28334  0.33567  1.25476
+     84   2.88583  5.39491  1.79381  2.06461  4.73890  3.24821  3.51210  4.22442  2.47141  3.51906  4.43601  2.95989  3.57031  2.79057  2.82788  2.02605  2.91163  3.62254  5.82805  4.41723    147 d - - B
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     85   2.90986  4.42406  3.70533  3.66371  3.02577  3.99009  3.90749  2.78363  3.56278  1.02082  3.24022  3.34355  4.36146  3.52102  3.78389  3.13807  2.95820  2.60948  5.03043  3.48016    148 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     86   2.57337  4.10245  3.03950  2.95233  2.09915  3.53742  3.15959  3.37138  2.66519  2.44003  3.54971  3.10382  3.71714  3.06888  3.13958  2.44794  3.05039  3.11306  4.61969  3.07664    149 f - - H
+          2.68621  4.42228  2.77522  2.73126  3.46357  2.40516  3.72497  3.29357  2.67744  2.69358  4.24693  2.90350  2.73735  3.18149  2.89804  2.37890  2.77502  2.98521  4.58480  3.61458
+          0.24291  3.02648  1.78874  0.58545  0.81386  0.48576  0.95510
+     87   2.29362  5.30873  1.92419  2.32474  4.26868  3.43187  3.46788  4.12970  2.37357  3.61146  4.35100  2.92576  3.98105  2.69850  2.60197  2.47206  2.54407  3.69618  5.74493  3.96335    152 d - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01185  4.83724  5.55959  0.61958  0.77255  0.87096  0.54223
+     88   2.24696  4.24235  4.56569  3.96478  2.41045  3.97137  3.29432  2.27668  3.43922  2.04964  3.19406  4.05576  4.33743  3.97000  3.38896  3.27217  3.06100  2.23241  4.18296  2.20711    153 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01185  4.83724  5.55959  0.61958  0.77255  0.87096  0.54223
+     89   3.80243  5.01974  5.81731  5.27268  3.70245  5.26548  5.70409  1.30084  5.15744  0.98923  3.04180  5.42350  5.39649  5.16571  5.17462  4.65797  4.03105  1.75151  5.84473  4.80632    154 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01185  4.83724  5.55959  0.61958  0.77255  0.62617  0.76494
+     90   2.48275  5.13868  3.18520  2.44727  3.97540  3.65122  3.65677  3.36126  2.16734  3.30486  3.19390  3.06911  4.04233  2.41632  2.75033  2.25069  2.41675  3.09873  5.62108  3.69504    155 k - - H
+          2.68595  4.42186  2.77509  2.73103  3.46377  2.40517  3.72421  3.29387  2.67761  2.69368  4.24695  2.90368  2.73754  3.18175  2.89730  2.37895  2.77536  2.98514  4.58473  3.61505
+          0.63487  1.25520  1.68753  1.39580  0.28453  0.74756  0.64154
+     91   2.43987  5.24839  2.75312  2.20207  4.11839  3.54175  3.72993  4.06095  2.07671  3.34429  3.98666  2.75679  3.72576  2.60349  2.28520  2.46158  2.79062  3.43756  5.68761  3.81452    172 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01352  4.70589  5.42824  0.61958  0.77255  0.34096  1.24163
+     92   2.56414  5.37054  2.84426  2.11401  4.71382  2.70860  2.88683  4.19851  2.19051  3.14492  4.41168  2.55924  4.03189  2.79129  2.63798  2.35762  3.09530  3.76022  5.80426  3.44686    173 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01035  4.97167  5.69402  0.61958  0.77255  0.60365  0.79145
+     93   2.86527  4.78061  2.95620  2.59670  4.27271  1.99448  3.84571  3.48713  2.08881  3.39073  4.33266  2.46895  3.64059  2.84730  2.63768  2.84659  2.50396  3.24160  5.73764  4.35043    174 g - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01035  4.97167  5.69402  0.61958  0.77255  0.46145  0.99524
+     94   2.57883  3.45102  3.31966  2.70191  4.02973  3.16828  3.76144  3.12068  2.26544  3.06289  4.10647  2.81108  2.70638  2.99156  2.57108  2.49596  2.68439  2.78596  4.48656  4.03099    175 k - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01001  5.00539  5.72774  0.61958  0.77255  0.51640  0.90799
+     95   3.00846  4.37852  4.95050  4.33851  2.03946  4.18408  4.51243  2.07907  4.13124  1.32746  2.71567  3.86888  4.53472  4.25457  4.14405  3.49709  3.23945  2.15194  4.98866  3.35208    176 l - - T
+          2.68632  4.42239  2.77534  2.73137  3.46298  2.40515  3.72509  3.29351  2.67755  2.69332  4.24641  2.90361  2.73734  3.18136  2.89815  2.37881  2.77519  2.98532  4.58491  3.61446
+          0.13280  2.11108  5.72774  1.00017  0.45858  0.46707  0.98573
+     96   2.55096  5.39506  2.51329  2.14467  4.73966  3.20813  3.84532  4.22553  2.37049  3.70015  4.43599  2.79265  3.16832  2.74582  2.82569  1.88822  2.42672  3.78548  5.82793  4.41687    180 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     97   2.55253  5.00371  2.91674  1.56530  3.77486  3.74196  3.71669  3.18678  2.77868  2.90828  3.00031  3.29724  3.28640  3.12328  3.07027  2.76413  2.89289  3.32236  3.74938  3.48354    181 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     98   2.59075  4.32000  2.44335  2.15201  3.95693  3.12347  3.34011  3.83572  2.30797  3.16698  3.93315  2.75363  3.60071  2.81660  2.61665  2.70578  2.85000  3.34465  3.67935  4.00275    182 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+     99   2.65092  5.35978  2.44414  1.82235  4.69093  3.44711  3.03513  3.63938  2.46445  2.69072  4.40412  3.13476  3.87902  2.43027  2.99516  2.67955  2.75495  3.20344  5.80088  4.03299    183 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    100   1.86496  3.02665  4.71869  4.11439  3.41506  3.78632  4.39467  1.72869  3.93413  2.03606  3.25110  4.17623  4.43415  4.09606  3.42450  3.02051  2.94480  2.04904  4.94015  3.76003    184 i - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    101   2.66380  3.60669  3.09016  2.70629  3.97052  3.12773  3.91117  3.25572  1.80561  2.74214  4.19581  3.23071  4.10037  2.51557  2.19861  2.73033  3.11863  2.97558  5.62300  4.27841    185 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    102   2.65525  3.61780  2.73206  2.59880  2.91626  3.69337  3.17740  3.91061  2.06495  2.87551  3.62080  2.65252  4.08468  3.01717  2.55140  2.50072  2.84956  3.37543  5.67937  3.86408    186 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    103   2.78549  3.75825  4.89230  4.27707  2.37628  4.09576  4.42870  1.58181  4.06146  2.16353  2.83229  4.25917  4.45832  4.19107  4.06819  3.40747  3.15724  2.08428  3.94244  2.32199    187 i - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    104   1.91854  4.04767  4.83572  4.22341  2.21465  3.82491  4.41156  2.18264  4.01792  2.17430  2.43077  4.22827  4.44431  4.15736  4.04152  2.82624  2.88622  2.07903  4.25105  3.74133    188 a - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    105   2.59846  4.94560  3.39451  2.56515  3.67443  3.44440  3.79808  3.54150  2.22767  2.11264  4.02778  3.19297  4.14629  3.16161  2.51054  2.63727  2.68778  3.11215  4.13689  2.62651    189 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    106   2.71202  4.65478  2.93025  2.07602  4.70407  3.24619  3.70431  4.18261  2.58938  3.67040  4.10390  3.00747  4.05496  1.41184  3.00214  2.55548  2.74962  3.75459  5.80879  4.40428    190 q - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510  
+    107   3.40758  4.70636  5.39472  4.82751  3.82844  4.73217  5.15283  1.33187  4.66862  1.85779  2.55181  4.88258  5.03394  4.81634  4.72035  4.07618  2.46891  1.37416  5.58393  4.41648    191 i - - H 
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    108   2.29107  3.23763  4.81578  4.20571  3.00975  3.26830  4.41487  2.37700  4.00619  1.39060  3.28560  4.22330  4.44775  4.15070  4.03923  2.94875  3.15303  1.86969  4.92930  3.75166    192 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    109   2.62933  4.07203  2.95927  2.08969  4.71415  3.53463  3.84677  3.97436  2.17805  2.82549  4.41873  2.79932  4.05232  2.53645  2.16719  2.25459  2.86145  3.76301  5.81311  4.40656    193 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    110   1.17650  4.82606  4.24050  3.83461  4.98724  1.08848  4.85992  4.42183  3.81285  4.07900  4.88120  3.97861  4.34888  4.10941  3.49121  2.50205  3.18154  3.58125  6.30917  5.10145    194 g - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    111   3.90271  5.14012  5.90469  5.33230  3.41122  5.28833  5.65529  2.02087  5.19062  0.88043  2.65524  5.45552  5.42442  5.15469  5.16815  4.66249  4.12260  1.40813  5.79888  4.77647    195 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    112   2.18892  5.38966  2.64044  1.97751  4.73333  3.65659  3.60437  3.92129  2.10090  3.35469  4.43069  2.33847  4.05005  2.60616  2.77179  2.58383  3.11351  3.51057  5.82316  3.92131    196 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    113   2.81051  5.07767  4.77644  4.29954  2.03535  4.57845  2.23184  3.59557  4.18346  3.18325  4.21755  4.37554  4.93163  4.33627  4.35340  3.88728  3.48134  3.41897  4.49144  0.85916    197 y - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    114   3.22459  2.61128  5.38969  4.79509  3.58979  4.68737  5.03975  1.79213  4.61293  0.89179  2.61919  4.84389  4.96801  4.69100  4.62327  4.02095  3.66625  2.57847  5.40913  4.29402    198 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    115   4.50357  5.94639  4.67261  4.49457  2.97674  4.90740  0.35314  4.75553  4.20979  3.98991  5.25041  4.60971  5.36272  4.62490  4.36557  4.47961  4.76464  4.60938  4.62703  2.51319    199 H - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    116   2.59851  4.33805  2.68311  2.05797  4.71676  3.15802  3.59362  3.65569  2.43439  3.32473  4.42034  2.78736  4.05190  2.70193  2.69422  1.73897  3.11362  3.60918  5.81450  4.40740    200 s - - H
+          2.68619  4.42226  2.77521  2.73118  3.46355  2.40514  3.72496  3.29355  2.67742  2.69356  4.24691  2.90348  2.73741  3.18131  2.89802  2.37888  2.77521  2.98510  4.58478  3.61505
+          0.04979  3.09322  5.73865  0.35009  1.21950  0.48576  0.95510
+    117   2.54785  4.42029  2.89622  2.25922  4.34868  3.66610  3.21799  3.71995  2.27125  3.07920  3.10189  2.25867  4.05899  2.34775  2.56766  2.85682  3.11428  3.36249  5.78309  3.93739    202 n - - T
+          2.68634  4.42198  2.77524  2.73138  3.46344  2.40486  3.72467  3.29300  2.67713  2.69352  4.24714  2.90371  2.73709  3.18145  2.89825  2.37911  2.77527  2.98532  4.58501  3.61528
+          0.09842  2.40225  5.73865  1.69597  0.20263  0.48576  0.95510
+    118   2.53322  5.34393  2.95935  2.59629  3.94657  1.84501  3.63806  4.14023  2.18335  3.64044  4.39013  2.55576  3.77395  2.95784  2.71428  2.21077  3.11477  3.72355  4.68564  4.39095    213 g - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    119   3.55513  4.24694  5.60079  5.05662  2.60993  4.96071  5.43324  0.97900  4.91818  2.09234  3.80321  5.12225  5.23216  5.06726  4.97588  4.32549  3.79818  1.34455  5.81250  4.64107    214 i - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    120   2.50668  3.55624  4.84676  4.23404  3.24346  4.08398  4.41611  1.66920  4.02684  2.01982  2.79518  4.23489  4.44784  4.16480  3.83668  2.91482  2.83994  1.71230  4.92013  3.32611    215 i - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    121   4.62495  5.94818  4.90176  4.71687  2.80207  5.05504  0.41821  4.71670  4.43975  3.92227  5.21366  4.70109  5.45885  4.74110  4.56151  4.57303  4.86606  4.59605  4.46431  2.05738    216 H - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    122   3.04282  4.16968  3.83274  3.22981  4.12386  3.92565  4.16387  3.45658  2.89535  2.79946  3.52962  3.63885  4.33284  3.40809  0.88367  3.03173  2.91452  3.20781  5.47983  4.24517    217 r - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    123   4.66549  6.56867  0.13049  3.73947  6.20930  4.51726  5.46620  6.15252  4.80154  5.54790  6.65359  4.31602  5.22661  4.77980  5.35908  4.57977  5.04873  5.69924  7.06132  6.05090    218 D - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    124   4.11594  5.30633  6.13178  5.57769  3.73657  5.59693  5.98457  1.50133  5.46568  0.67788  3.07617  5.76705  5.63423  5.36401  5.43088  5.00606  4.33175  2.14525  5.97972  5.01356    219 L - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    125   4.55719  6.24846  4.80697  4.34215  5.94023  4.73956  5.02576  5.52333  0.17090  4.86848  5.87217  4.66859  5.24422  4.23030  3.41495  4.59394  4.77093  5.20290  6.57866  5.65826    220 K - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    126   2.73388  4.87911  3.10327  2.90832  4.07991  3.41413  4.01646  3.20246  2.89177  2.38683  3.78561  3.39051  1.51394  3.22647  3.32105  2.31617  2.81372  3.19214  5.43675  4.15025    221 p - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    127   2.30763  5.39894  2.49711  1.50775  4.74209  3.53358  3.60730  4.22742  2.31483  3.70337  3.89187  2.94609  4.05547  2.65035  3.08133  2.29509  3.12215  3.78862  5.83238  4.42137    222 e - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    128   4.24075  6.04161  4.10323  4.13804  5.66046  4.44992  5.52992  5.77835  4.64675  5.26705  6.30900  0.15130  5.17553  4.91694  4.94682  4.32646  4.70552  5.25421  6.75952  5.61338    223 N - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    129   3.55135  3.88080  5.58388  5.03211  3.05772  4.93598  5.38843  0.81084  4.88763  1.84199  3.74557  5.09695  5.20522  5.02095  4.93631  4.29650  3.79207  1.75582  5.75938  4.60163    224 i - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510 
+    130   4.26500  5.46000  6.21355  5.61602  2.31085  5.64571  5.88455  2.68862  5.47780  0.52109  2.36789  5.81754  5.61663  5.25881  5.37169  5.03996  4.45544  2.72136  5.81387  4.88779    225 L - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    131   3.14725  3.80930  5.11896  4.51210  2.75868  4.35237  4.69393  1.48763  4.30885  1.32733  3.15909  4.51494  4.68518  4.42027  4.31553  3.67228  3.37834  1.91515  5.14039  3.60311    226 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    132   2.83132  4.28838  2.02200  2.41335  4.70055  3.12743  3.31546  4.17875  2.06503  3.46693  4.09733  2.49326  4.05387  2.94892  3.07895  2.27711  2.89161  2.90947  5.80603  4.40188    227 d - - E
+          2.68620  4.42227  2.77521  2.73125  3.46356  2.40515  3.72496  3.29356  2.67743  2.69346  4.24692  2.90348  2.73741  3.18137  2.89794  2.37889  2.77521  2.98513  4.58479  3.61505
+          0.19179  2.92011  2.11536  0.31959  1.29625  0.48576  0.95510
+    133   2.77846  5.34345  2.73873  2.12504  4.68884  3.31622  3.10327  4.17503  2.07146  3.64885  4.14408  2.35495  3.55373  2.53396  2.68259  2.30312  2.80970  3.73426  5.77591  4.07717    229 k - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01122  4.89146  5.61380  0.61958  0.77255  0.46383  0.99121
+    134   2.76231  5.37627  2.40965  2.30431  4.72103  3.48860  3.46007  4.20680  2.15285  3.68141  4.41704  2.22463  3.54282  2.67483  2.66394  2.48608  2.48229  3.08661  5.80911  4.39830    230 k - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01030  4.97674  5.69908  0.61958  0.77255  0.42506  1.06054
+    135   2.88621  4.31580  2.58861  2.52891  4.00821  1.80604  3.64216  3.70404  2.55848  3.01103  3.82083  2.93142  3.28125  2.96153  3.15140  2.63196  2.92652  3.07947  5.65563  3.39061    231 g - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    136   2.74326  5.32913  2.62872  2.23118  4.20190  3.27586  3.01088  3.39612  2.54602  3.28443  3.99578  2.66732  4.06020  2.45230  2.82728  2.54748  2.65672  2.69485  5.77785  3.49295    232 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    137   2.61635  3.28525  4.16732  3.71739  2.98202  4.03403  4.34546  2.03775  3.50788  1.92540  3.47356  3.38535  3.11745  3.96570  3.52677  3.32696  2.46663  1.86856  4.97202  3.78516    233 v - - E
+          2.68644  4.42087  2.77438  2.73125  3.46306  2.40580  3.72561  3.29182  2.67742  2.69394  4.24637  2.90298  2.73752  3.18209  2.89809  2.37898  2.77573  2.98487  4.58490  3.61464
+          0.36530  1.19470  5.73865  2.01193  0.14356  0.48576  0.95510
+    138   2.92386  3.12674  3.30583  2.50241  4.41812  3.73989  3.57074  3.83865  1.16713  3.42239  3.64701  3.25964  4.12762  3.06518  2.74407  2.94589  3.15200  3.22587  5.64420  3.71460    253 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    139   3.61791  5.07369  5.93139  5.42030  4.01697  5.40165  5.95563  1.06228  5.32659  1.08905  3.76387  5.56598  5.56723  5.42106  5.39317  4.81179  4.11011  1.74432  6.14737  5.05160    254 i - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    140   1.74479  2.79152  4.35686  3.77898  3.55350  2.78668  4.34505  2.08763  3.66685  2.55990  3.56128  3.98833  4.38080  3.89329  3.86150  2.46831  2.34811  2.41028  5.05799  3.86488    255 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    141   4.66549  6.56867  0.13049  3.73947  6.20930  4.51726  5.46620  6.15252  4.80154  5.54790  6.65359  4.31602  5.22661  4.77980  5.35908  4.57977  5.04873  5.69924  7.06132  6.05090    256 D - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    142   4.66482  5.73614  5.86239  5.64956  0.40883  5.43325  4.33355  3.86711  5.42110  2.16428  4.36705  5.11239  5.65371  5.16689  5.27011  4.83252  4.86624  3.98432  3.74189  2.69037    257 F - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    143   3.93699  5.85566  3.02816  3.87037  6.00993  0.21285  5.44927  5.75466  4.70121  5.27717  6.21696  4.31536  4.99427  4.76567  5.12629  4.02226  4.42780  5.10478  6.99282  5.96830    258 G - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    144   2.54355  3.67295  4.73868  4.13265  2.71576  4.06852  3.76754  2.37455  3.94756  1.20416  3.31174  3.74431  4.43365  4.10500  4.00521  2.64259  3.14725  2.29206  4.93223  3.75278    259 l - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03189  5.01631  3.69859  0.61958  0.77255  0.48576  0.95510
+    145   0.77520  2.86695  4.81978  4.47036  4.95592  3.15951  5.20700  4.36343  4.38394  4.08078  4.90451  4.25075  4.38058  4.58838  4.56864  1.45304  3.34905  3.34992  6.35477  5.22001    260 a - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.07711  4.99453  2.69658  0.61958  0.77255  0.54567  0.86620
+    146   2.54977  3.79925  3.16699  2.32606  4.48674  3.31547  3.84408  3.47518  1.75582  3.12339  4.25869  2.84258  4.04145  2.96441  2.18943  2.71334  2.91887  2.95414  5.67187  4.30075    261 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.13472  4.92824  2.13029  0.61958  0.77255  0.70219  0.68419
+    147   2.64685  3.78445  3.06669  2.61534  3.32325  3.67596  3.69246  3.14713  2.01231  2.43193  3.43451  3.16113  4.06301  2.47274  3.08778  2.74475  2.84906  2.65428  5.37440  4.07606    262 k - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.29473  4.80574  1.39802  0.61958  0.77255  0.92027  0.50818
+    148   2.40579  4.15423  4.25399  3.66267  2.39272  3.57693  3.44550  2.33935  3.03827  1.86796  2.97007  3.83355  4.18573  3.73297  3.67827  3.10851  2.93289  2.21754  4.76738  2.96352    263 l - - .
+          2.68635  4.42219  2.77489  2.73146  3.46367  2.40530  3.72500  3.29419  2.67720  2.69370  4.24630  2.90362  2.73727  3.18122  2.89818  2.37860  2.77478  2.98583  4.58472  3.61420
+          0.77167  0.63015  5.24955  1.50734  0.25038  0.20147  1.70117
+    149   2.68930  5.13793  2.99383  2.28756  4.12167  3.02811  3.40047  2.83046  2.53990  2.67433  3.91490  2.66806  3.85841  2.95123  3.08518  2.54554  2.43488  3.14237  4.83794  3.11842    281 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    150   2.67960  3.59834  3.08049  2.32634  4.00400  2.85568  3.65072  3.26198  2.22635  2.80014  3.89773  3.03566  3.90780  2.84131  2.77630  2.59674  2.54121  2.94346  4.66327  3.60288    282 k - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    151   2.78407  5.36932  2.80723  2.38070  3.95652  3.28210  3.31902  3.80407  2.38757  3.23090  4.41260  2.26860  2.87333  2.94776  2.55475  2.11230  2.82314  3.31603  5.80800  4.40313    283 s - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    152   2.55066  5.37311  2.42428  2.58328  4.70981  2.65546  3.66067  3.46611  2.34139  3.39818  4.41598  2.44705  3.58966  2.48003  2.87086  2.30355  2.92043  3.58081  5.81084  3.32103    284 s - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    153   2.61131  5.36709  3.05324  2.00706  4.70125  2.53001  3.45141  4.17959  2.46541  3.54879  4.41063  3.13225  3.27183  2.67970  2.77280  2.14590  2.62504  2.97295  5.80635  3.79465    285 e - - S
+          2.68619  4.42226  2.77520  2.73124  3.46320  2.40514  3.72495  3.29355  2.67742  2.69356  4.24691  2.90348  2.73740  3.18147  2.89802  2.37888  2.77520  2.98519  4.58478  3.61504
+          0.03620  3.43177  5.73865  0.40966  1.09027  0.48576  0.95510
+    154   2.80870  4.76397  2.82688  2.35901  3.53520  3.31737  3.24083  3.53679  2.31494  2.98485  3.52265  2.69923  3.15465  2.90046  2.56489  2.40361  2.83318  3.04461  5.74293  3.76697    287 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    155   2.38638  3.55872  3.84850  3.27925  3.07902  3.89951  3.49984  3.07191  2.87600  2.13071  2.79826  2.94436  3.28103  3.24012  3.30127  2.77627  2.52689  2.66914  5.17020  2.84075    288 l - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    156   2.88266  4.79637  2.63708  2.49106  4.69372  3.27452  3.02757  4.17056  2.31920  3.54781  3.84892  2.54158  3.83133  2.71114  2.83815  2.34796  2.07167  3.53868  4.84477  3.26548    289 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    157   2.55115  5.22307  2.81541  2.42597  3.84088  2.72211  3.45978  3.70939  2.65113  3.50012  4.03956  3.00145  3.26637  2.92366  3.12986  2.10982  2.09681  2.95270  4.42058  4.32902    290 t - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    158   2.79383  4.53543  3.94528  3.00256  2.28876  3.25886  4.19260  2.53698  3.31063  2.13485  3.51266  3.25465  3.61933  3.02975  2.60672  3.04108  3.13630  2.22820  5.12884  3.03437    291 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    159   2.54133  2.27249  3.62507  3.14565  3.48798  3.47382  4.20805  2.87324  3.24770  2.61629  3.62417  3.76153  4.31084  3.45605  3.15192  3.19594  2.77273  1.44309  5.11140  3.89714    292 v - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    160   2.50560  4.02210  4.21483  3.69251  4.03927  0.87585  4.50859  3.18042  3.62456  3.12203  4.01557  3.91946  4.34666  3.89680  3.91281  2.66630  3.23503  2.52015  5.49804  3.97346    293 g - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    161   2.98792  5.00679  3.18026  3.47531  5.09253  3.65988  4.75357  4.53531  3.72802  4.18133  4.99276  3.79669  4.37930  3.97717  4.12874  1.60941  0.74054  3.97784  6.39182  5.11951    294 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    162   2.69840  5.26022  3.00961  2.31122  4.20998  3.68086  3.63617  3.20701  2.41779  2.58849  4.31499  2.98486  2.62271  2.99075  2.13729  2.36313  3.11573  3.42385  5.72545  3.54571    295 r - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    163   2.71301  5.29924  2.59488  2.14743  3.52695  3.04037  3.28275  4.06670  2.61594  3.34508  4.35002  2.84026  3.31113  2.97459  2.36266  2.86533  2.70674  3.41928  3.03699  3.23042    296 e - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    164   4.65993  5.73598  5.69662  5.49898  1.97465  5.32012  3.31709  4.36240  5.29326  3.66395  4.92323  4.93743  5.59573  5.06816  5.17473  4.69695  3.41633  4.25844  2.61302  0.51590    297 Y - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    165   2.46851  3.63596  4.34730  3.76113  3.49978  4.00900  4.30977  2.55613  3.41377  2.11254  1.89168  3.40620  4.37893  3.86942  2.23584  3.08926  3.14320  2.13937  5.00600  3.81292    298 m - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    166   0.54633  4.79516  4.59072  4.34047  5.33605  3.22550  5.27451  4.80651  4.37656  4.47607  5.24769  4.21379  3.02084  4.58677  4.60871  1.81435  3.40538  4.05386  6.66459  5.53199    299 A - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    167   3.08666  5.02380  4.02349  3.92167  5.10908  3.73669  5.07487  4.62556  4.04836  4.33998  5.22795  3.34786  0.41351  4.38870  4.30726  3.26072  3.60085  3.40472  6.47905  5.20179    300 P - - H
+          2.68622  4.42144  2.77523  2.73111  3.46358  2.40517  3.72498  3.29358  2.67745  2.69359  4.24694  2.90351  2.73743  3.18126  2.89786  2.37891  2.77523  2.98522  4.58481  3.61507
+          0.03484  3.47295  5.73865  0.99675  0.46057  0.48576  0.95510
+    168   3.66837  6.19086  2.84947  0.45189  5.55161  3.90523  4.43200  5.09782  3.30487  4.55035  5.42336  3.03786  4.53514  3.60153  3.37398  3.54999  3.95969  4.65772  6.64024  5.17650    305 E - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510 
+    169   2.79774  4.32598  4.68241  3.67608  3.42171  4.06471  4.38713  2.01470  3.90321  1.87174  3.44282  4.15860  4.43014  3.77035  3.25202  3.36713  2.95239  1.31877  3.77234  3.76466    306 v - - H
+          2.68603  4.42242  2.77519  2.73104  3.46342  2.40506  3.72511  3.29371  2.67728  2.69322  4.24707  2.90364  2.73756  3.18163  2.89801  2.37893  2.77519  2.98535  4.58494  3.61520
+          0.12919  2.22240  4.35495  1.23224  0.34480  0.48576  0.95510
+    170   2.91184  3.76308  4.76588  4.15799  3.39752  4.06920  3.82796  1.60071  3.96642  1.39613  3.17824  3.65225  4.43387  4.11848  4.01348  2.94594  3.14403  2.21737  4.92444  3.43929    311 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00999  5.00664  5.72898  0.61958  0.77255  0.51297  0.91308
+    171   2.62785  5.06480  3.29796  2.67561  3.73804  3.41086  3.92577  3.21358  2.32640  2.15096  3.31180  2.55443  4.11004  2.47045  2.33927  2.70318  3.11578  3.12852  5.57146  4.24107    312 l - - C
+          2.68631  4.42245  2.77511  2.73076  3.46350  2.40522  3.72547  3.29356  2.67765  2.69366  4.24573  2.90389  2.73738  3.18142  2.89826  2.37846  2.77520  2.98520  4.58530  3.61473
+          0.62427  1.87899  1.16602  1.98855  0.14722  0.46912  0.98231
+    172   2.60166  5.18307  2.62016  2.19793  3.35206  2.39740  3.57105  3.96340  2.18128  3.47543  4.23188  3.01161  3.92489  2.82990  2.86326  2.33987  2.67701  3.55746  5.63416  3.78538    327 k - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01428  4.65191  5.37425  0.61958  0.77255  0.24611  1.52250
+    173   2.37600  3.94341  2.81761  2.45806  4.08381  2.38833  3.32666  4.15213  2.47322  3.64753  4.39446  2.71786  3.74359  2.39493  2.76163  2.38666  3.00597  3.01776  5.79219  3.82026    328 a - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00998  5.00778  5.73012  0.61958  0.77255  0.47101  0.97916
+    174   2.81816  4.87774  2.88922  2.34131  3.91699  3.47934  3.84840  3.76601  2.22767  3.10881  4.41163  2.46519  2.75598  2.51039  2.43545  2.43680  2.76354  3.54179  5.80719  3.84984    329 k - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    175   2.74169  5.33416  2.58184  2.32653  3.61666  2.33545  3.50275  4.12419  2.36762  3.50261  3.56274  2.91332  3.07814  2.74477  2.96926  2.79421  2.92848  3.32496  5.78164  2.72284    330 e - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    176   2.48397  4.72191  2.72922  2.94719  3.45604  3.83733  2.73484  2.72590  3.03376  2.94128  3.81928  3.51045  4.21965  3.13222  3.31573  2.84267  3.12967  2.71705  3.94971  1.76193    331 y - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    177   2.88858  5.15756  2.48812  2.69267  3.68939  2.20273  3.90720  3.84889  2.69072  3.17648  4.22648  3.21985  3.19313  3.04303  3.16266  2.07644  2.02474  3.50391  5.64990  3.69862    332 t - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    178   2.44412  5.27089  3.18567  2.52594  4.01181  3.49400  3.20300  3.68711  2.26882  2.99802  4.32458  3.16791  2.73532  2.67304  2.47574  2.35896  2.41445  3.31659  5.73361  3.79657    333 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    179   2.27957  5.36842  3.14470  2.24142  4.70283  3.35867  3.70433  4.18054  1.84880  3.00297  4.41216  3.13478  2.50109  2.87247  2.49374  2.50485  2.88881  3.75338  5.80713  4.40386    334 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    180   2.25487  3.19836  3.67383  3.53894  3.58335  3.60706  4.24810  2.30247  3.45618  2.57768  3.58074  3.40343  4.33674  3.48890  3.71724  2.25302  2.94661  1.56396  5.07167  3.86608    335 v - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    181   3.32488  6.23611  0.30142  2.99559  5.85936  3.97225  4.81661  5.46625  4.07634  5.00781  5.98660  3.57219  4.70996  4.04099  4.76451  3.76774  4.26196  4.95940  7.04785  5.56474    336 D - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    182   2.97530  4.34655  4.92112  4.31006  3.42469  4.15298  4.48903  1.67409  4.10270  2.14170  2.44181  4.30839  4.51041  4.23558  4.11915  3.46567  2.80277  1.45020  3.28394  3.56694    337 v - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    183   4.60767  5.71652  5.61554  3.89031  2.18526  5.28181  4.15190  4.32304  5.18037  3.62888  4.88484  4.90634  5.56392  5.01906  5.10312  4.65700  4.81381  4.22147  0.60655  1.74323    338 W - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    184   1.30551  4.78823  4.65738  4.37945  5.36630  2.58206  5.28849  4.84019  4.38318  4.50739  5.27020  4.22569  4.39579  4.59600  4.61395  0.79404  2.89139  4.06528  6.68751  5.56026    339 s - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    185   2.44153  3.17932  4.87400  4.25972  2.53121  4.09082  4.42403  2.33144  4.04748  1.34403  2.92510  4.24940  4.45392  4.18053  4.05982  3.14600  3.15398  2.13810  4.92017  3.14864    340 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    186   2.22507  4.96728  4.63623  4.63233  5.66307  0.33314  5.62287  5.16416  4.86793  4.86816  5.66661  4.43512  4.57282  5.01497  4.99264  3.26151  3.63533  4.32703  6.92990  5.89905    341 G - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    187   2.93009  2.13614  4.95885  4.35253  3.48038  4.19799  4.54424  1.68794  4.14925  1.93394  3.18432  4.35359  4.55452  4.28834  4.17024  3.34008  3.23972  1.60527  5.03746  3.47367    342 v - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    188   3.21831  4.55127  5.17022  4.58630  3.70338  4.47717  4.86313  1.30610  4.40976  1.92114  2.79907  4.62299  4.81179  4.56490  4.45688  3.52794  2.67243  1.42404  5.34369  4.16408    343 i - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    189   2.77853  3.56970  4.91220  4.29933  2.66878  4.13468  4.46922  2.12981  4.08926  1.13811  3.14072  4.29275  4.49323  4.21981  4.10205  3.44689  2.88537  2.20246  4.95897  3.46211    344 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    190   2.08301  4.31008  4.80905  4.20025  2.66597  4.08391  3.54227  2.07553  4.00182  2.35024  3.19529  4.21899  4.44796  4.14611  4.03654  3.39206  3.15615  2.32332  2.91148  1.86433    345 y - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    191   2.65126  3.79080  3.03118  1.37895  4.54227  3.68257  3.87660  3.27048  2.56225  3.53374  4.30787  2.88399  4.07460  2.72714  3.11894  2.49943  2.86114  3.20681  5.71940  3.61825    346 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    192   2.75949  4.33120  4.86063  4.24972  2.93412  4.11800  4.44873  2.58063  4.04775  1.34098  1.86205  4.26240  4.47769  4.18564  4.07448  3.30982  2.87183  2.17494  4.95131  3.25026    347 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    193   2.13730  3.34433  4.84746  4.23449  2.67079  4.08305  4.41495  2.45417  4.02682  1.45586  2.95446  4.23448  4.44687  4.16424  3.65241  3.39295  2.78239  2.10310  4.91833  3.10946    348 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    194   2.61714  3.04119  3.51958  2.50105  3.16562  3.44068  4.02999  3.26384  2.78703  2.46125  3.90521  2.94061  4.18669  3.26384  2.94427  2.45451  1.92365  2.96026  5.36672  3.77569    349 t - - H
+          2.68592  4.42131  2.77530  2.73134  3.46364  2.40523  3.72505  3.29364  2.67751  2.69365  4.24624  2.90357  2.73750  3.18157  2.89769  2.37886  2.77510  2.98507  4.58487  3.61513
+          0.08274  2.77459  4.07273  1.24373  0.34011  0.48576  0.95510
+    195   2.74009  5.38236  2.60734  2.58658  4.30151  1.49346  3.57775  4.19577  2.06867  3.68256  4.42710  2.84258  4.06100  2.86136  2.79826  2.78642  3.12785  3.76776  5.82019  4.41533    355 g - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02515  5.00240  4.01100  0.61958  0.77255  0.52459  0.89600
+    196   2.87057  4.15783  2.81932  2.15097  3.67482  3.00161  3.44561  3.53712  2.01194  3.52030  4.39830  2.84675  4.04172  2.62971  2.18111  2.65254  2.90372  3.46034  5.79407  3.92999    356 k - - S
+          2.68632  4.42239  2.77496  2.73101  3.46368  2.40527  3.72508  3.29339  2.67739  2.69369  4.24616  2.90361  2.73734  3.18160  2.89815  2.37901  2.77533  2.98486  4.58491  3.61430
+          0.06990  2.74572  5.70978  1.46974  0.26135  0.43968  1.03351
+    197   2.53761  4.57755  3.85895  3.05555  3.06219  3.90225  3.89097  2.90555  3.23603  1.98376  3.43681  3.14844  2.18635  3.28921  3.56902  2.76101  2.38583  2.48063  5.16546  3.65117    363 l - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    198   2.94035  4.49377  4.16973  3.59341  3.59928  3.99457  4.28692  2.57573  3.48228  2.11382  3.59630  3.88641  1.19333  3.75706  3.46613  3.08341  3.17527  2.51467  5.10025  3.66586    364 p - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    199   2.95410  3.97958  4.76382  4.16399  1.23466  4.10162  4.38107  2.78567  3.65586  2.19089  3.46719  4.20671  3.78920  4.13156  4.03525  3.25126  3.18603  2.50296  2.73984  2.86766    365 f - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    200   2.72297  4.82530  2.62940  2.35446  3.83755  3.31971  3.71413  4.17131  2.26174  3.54363  4.14174  3.02369  2.60946  2.49179  2.66057  2.21727  2.99115  3.74587  4.55596  3.10965    366 s - - S
+          2.68620  4.42227  2.77522  2.73112  3.46340  2.40515  3.72496  3.29334  2.67743  2.69357  4.24692  2.90349  2.73742  3.18148  2.89803  2.37889  2.77522  2.98520  4.58479  3.61505
+          0.07731  2.84051  4.13492  0.30572  1.33404  0.48576  0.95510
+    201   2.63880  5.38435  2.63657  2.22720  4.72697  1.94780  3.15235  3.87964  2.57669  3.68860  4.42577  2.57921  3.16991  2.74291  2.86900  2.50219  2.85278  3.77370  5.81843  4.40865    368 g - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01003  5.00344  5.72579  0.61958  0.77255  0.52175  0.90012
+    202   2.40102  4.71375  2.46996  2.13243  4.71840  3.11745  3.05416  3.48265  2.25142  3.16134  4.41932  2.93828  3.25177  2.60824  2.79040  2.58260  2.90071  3.38079  5.81277  4.40438    369 e - - S
+          2.68658  4.42180  2.77453  2.73123  3.46394  2.40505  3.72421  3.29333  2.67765  2.69382  4.24730  2.90354  2.73686  3.18110  2.89829  2.37906  2.77522  2.98525  4.58428  3.61543
+          0.55463  1.48984  1.60791  1.39890  0.28351  0.52175  0.90012
+    203   2.69338  5.29005  2.51143  2.25105  4.62988  2.84270  3.49832  3.48405  2.27737  3.31427  4.33211  2.56706  3.20350  2.85310  2.67590  2.21378  2.73620  3.67787  5.72586  4.31806    375 s - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01250  4.78398  5.50633  0.61958  0.77255  0.95212  0.48763
+    204   2.65942  5.19894  2.69156  2.28179  3.77027  3.19251  3.77484  3.06173  2.43464  2.99400  3.94013  2.58274  3.44930  2.63512  2.62020  2.46578  2.71730  3.35179  5.65696  3.80565    376 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01250  4.78398  5.50633  0.61958  0.77255  0.77169  0.62033
+    205   2.38920  5.21254  2.73488  2.26876  4.51445  3.29559  3.03245  3.05648  2.42252  2.83088  3.97624  2.72691  3.66747  2.74292  2.65924  2.79642  2.87825  3.04317  5.67196  3.47007    377 e - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01186  4.83615  5.55849  0.61958  0.77255  0.33713  1.25111
+    206   2.65422  4.48489  1.88534  2.29942  4.71042  3.12833  3.84224  3.67843  2.58000  3.67468  4.41498  2.22848  4.04754  2.86157  2.64414  2.33478  2.73698  3.75923  5.80928  4.40246    378 d - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01003  5.00344  5.72579  0.61958  0.77255  0.52175  0.90012
+    207   2.52228  5.35256  2.79874  2.27245  4.68298  3.15080  3.25420  3.81263  2.42135  3.03021  2.98061  3.02733  3.41549  2.09266  2.89624  2.43800  3.03420  3.22791  5.79412  4.39217    379 q - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01003  5.00344  5.72579  0.61958  0.77255  0.52175  0.90012
+    208   2.88352  5.03264  3.01718  2.64158  3.36791  3.41419  3.67586  2.82361  2.46533  2.06980  3.25199  2.87105  3.91016  2.67457  2.54739  2.67076  3.11488  3.35644  5.54543  3.24074    380 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01003  5.00344  5.72579  0.61958  0.77255  0.52175  0.90012
+    209   2.31106  5.21929  3.20358  2.11286  3.58411  3.54755  3.12693  3.74178  2.35878  3.37262  4.27754  3.18132  3.64073  2.21825  2.83044  2.63943  3.03559  2.71879  4.50670  3.34948    381 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01003  5.00344  5.72579  0.61958  0.77255  0.46390  0.99109
+    210   2.74907  4.02445  4.23598  3.43708  3.16042  3.98772  3.66116  2.29352  2.78065  1.91975  2.65717  3.64306  4.00461  3.79624  2.62994  3.12682  2.72367  2.05105  5.03295  3.83444    382 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    211   2.79706  4.32223  4.14412  4.07508  2.44930  4.05985  3.54709  1.67401  3.90204  2.17979  2.94629  3.31750  4.42562  4.07034  3.98057  2.91878  2.88141  2.01026  4.94063  2.95520    383 i - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    212   2.43063  3.51667  2.84063  2.33381  3.23751  3.53757  3.64461  3.61354  2.52297  3.04234  3.80037  3.02528  3.31294  2.77439  2.36706  2.71893  3.04140  2.71650  5.64517  3.47973    384 e - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    213   2.54995  5.35768  3.14585  2.23433  4.68798  3.33616  3.38625  3.80986  2.09254  2.85705  3.68757  2.56176  4.05535  2.40160  2.38927  2.57618  3.04385  3.36418  5.79929  3.79887    385 k - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    214   2.66499  5.02053  2.80345  2.59207  4.23983  3.19081  3.94632  1.95336  2.43621  2.96229  3.77095  2.92719  4.12615  3.11304  2.86357  2.94448  2.42822  2.54184  5.53679  4.21766    386 i - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    215   2.79062  4.84420  3.48859  2.83007  4.02200  3.06268  4.01637  2.98055  2.36084  1.68419  3.06982  3.40535  3.56488  2.89781  2.78978  2.64270  2.97298  2.81255  5.39215  4.11258    387 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    216   2.78422  4.40067  2.87114  2.38957  4.66317  2.42774  3.11725  3.68493  2.29738  3.11118  3.80555  3.07548  3.38861  2.66839  2.52841  2.36297  2.74889  3.71883  4.85618  3.72852    388 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.04975  5.01631  3.17248  0.61958  0.77255  0.48576  0.95510
+    217   2.55009  3.88585  3.08502  2.47179  4.52328  2.60499  3.86026  3.74333  2.31088  3.21633  3.94275  3.03087  2.50945  2.97834  2.41589  2.69163  2.38722  3.38360  5.70135  4.11095    389 k - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01030  4.97686  5.69921  0.61958  0.77255  0.59090  0.80705
+    218   2.71816  5.35510  2.47492  2.28903  4.69101  3.44039  3.67059  2.92462  2.15295  3.03900  4.39818  2.98975  2.40750  2.74839  2.76016  2.49540  2.85213  3.74081  5.79327  4.38792    390 k - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02103  4.97686  4.27462  0.61958  0.77255  0.59090  0.80705
+    219   2.59242  4.56547  3.37418  3.24570  3.28039  3.87349  3.78552  2.80260  2.91515  1.85640  3.67045  2.94464  3.03710  3.48913  3.31352  2.93163  2.57101  2.12270  4.60315  3.29903    391 l - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01041  4.96623  5.68858  0.61958  0.77255  0.61678  0.77584
+    220   2.76552  5.35116  2.75065  2.09233  4.26840  3.39661  3.23930  3.45666  2.13782  2.93921  3.69074  2.78256  2.85112  2.85423  2.61182  2.41762  3.01864  3.73701  5.78920  4.16743    392 e - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01041  4.96623  5.68858  0.61958  0.77255  0.61678  0.77584
+    221   2.56616  4.88573  3.26662  2.33696  2.41520  3.27403  3.41068  2.92250  2.70761  2.68623  3.97070  3.19787  3.38122  3.16656  2.79903  2.47364  2.99470  2.86843  4.82552  3.32054    393 e - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01041  4.96623  5.68858  0.61958  0.77255  0.61678  0.77584
+    222   2.62567  5.35084  2.04845  2.35215  4.39252  3.47212  3.16243  3.98892  2.45186  3.65226  3.66396  2.66846  2.63580  2.82810  3.05661  2.22708  2.99549  3.54011  5.78899  3.92777    394 d - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03667  4.96623  3.53930  0.61958  0.77255  0.61678  0.77584
+    223   2.86103  4.03193  3.18635  2.38909  3.31435  3.61153  3.49109  2.70908  2.69769  2.69388  3.88535  3.22191  3.67076  3.11276  2.73635  2.49324  3.00545  2.72730  2.94731  2.96802    395 e - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01875  4.94025  4.47244  0.61958  0.77255  0.67631  0.71028
+    224   2.62521  5.12447  2.77972  2.44738  3.31605  3.53418  3.86652  3.33309  2.47319  3.03557  4.18886  3.10134  2.42408  2.60018  2.70100  2.64509  2.92363  3.22521  3.41935  3.46519    396 p - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.05901  4.93227  2.99396  0.61958  0.77255  0.69360  0.69269
+    225   2.68343  5.20702  2.88582  2.22963  3.55567  3.45903  3.65367  3.49248  2.11994  2.97314  4.26172  2.80968  3.57686  2.44336  3.06162  2.53581  2.67303  3.18308  3.73101  3.66292    397 k - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01130  4.88456  5.60691  0.61958  0.77255  0.78866  0.60597
+    226   2.68707  4.98468  2.82158  2.38405  3.75917  3.36024  3.65392  3.18317  2.38508  2.73942  3.76303  3.22111  3.36652  3.04584  2.96704  2.31757  2.64759  2.95752  3.21600  3.40268    398 s - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.11345  4.88456  2.30573  0.61958  0.77255  0.78866  0.60597
+    227   2.79298  3.84213  2.48108  2.52210  3.99851  3.60747  3.12972  3.13545  2.48018  3.05991  4.13768  2.83211  3.54520  2.93964  2.41588  2.35619  2.76810  2.97839  5.56015  3.44494    399 s - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02807  4.78362  3.94704  0.61958  0.77255  0.95264  0.48731
+    228   2.58191  4.56682  2.77742  2.37170  4.46635  3.58143  3.77449  3.50815  2.36445  2.67587  4.22448  2.86502  2.73607  2.80387  2.79297  2.07848  2.75446  3.53442  5.63386  3.74575    400 s - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.14447  4.76826  2.07130  0.61958  0.77255  0.97412  0.47405
+    229   2.74120  5.02625  2.90214  2.38037  3.96892  2.81361  3.75340  3.09744  2.29181  2.85276  3.79351  2.85134  3.31773  2.88600  2.57247  2.48932  2.74923  2.81409  5.51153  4.15648    401 k - - .
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02950  4.63827  3.94280  0.61958  0.77255  1.12880  0.39071
+    230   2.65814  5.03703  2.72915  2.44094  4.30481  3.19996  3.74471  3.73960  2.51991  2.72378  3.12113  3.05398  2.98987  2.79382  2.49179  2.12708  2.96796  3.38544  5.51898  3.52938    402 s - - .
+          2.68724  4.42293  2.77612  2.73159  3.46162  2.40699  3.72369  3.29398  2.67731  2.69321  4.24701  2.90285  2.73662  3.18257  2.89624  2.37860  2.77511  2.98573  4.58252  3.61251
+          0.60323  0.80254  5.34581  2.99471  0.05135  0.22221  1.61320
+    231   2.51767  5.38833  2.69504  1.91983  4.73145  3.65677  3.84405  3.51135  2.26714  3.33248  4.42951  2.74739  2.83044  2.63263  2.69535  2.26534  2.89575  3.77792  5.82218  4.12814    442 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    232   2.61324  5.33087  2.55247  1.71577  3.78905  3.51981  3.85697  4.11872  2.53837  3.37618  3.68276  2.71899  3.50504  2.96215  2.76975  2.43182  2.62759  3.19721  4.83386  4.08215    443 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    233   1.85315  2.66076  4.74963  4.14369  2.72361  2.76389  4.40211  2.66580  3.95769  1.60680  3.08425  4.19191  4.43908  4.11400  4.01342  3.37949  2.94810  2.35782  4.93743  3.75833    444 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    234   2.54113  3.93957  3.31567  2.58263  3.59686  3.36801  3.93655  2.84244  1.77469  2.55244  4.12290  3.02474  4.11900  2.54032  2.70090  2.93506  2.79964  3.23719  5.55956  3.97978    445 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    235   2.66035  5.38903  1.80529  2.16718  4.22724  3.25823  3.17680  4.00903  2.28647  3.50730  4.43018  2.97613  4.05032  2.48614  2.98498  2.31241  3.11375  3.77870  5.82277  3.97909    446 d - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    236   3.21254  4.56529  5.14365  4.53738  1.97526  4.40976  4.73239  2.19759  4.34073  1.04052  3.41232  4.55986  4.72994  4.44093  4.35221  3.72900  3.00622  2.20314  5.16040  3.53582    447 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    237   2.97518  4.05135  5.35921  4.78478  3.77817  4.66169  5.06989  1.35059  4.61468  1.50253  2.60400  4.82061  4.97178  4.75525  4.65269  4.00168  3.59517  1.52175  5.50364  4.33590    448 i - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    238   2.63113  4.16111  2.70523  2.01221  4.32546  2.89528  3.69801  3.91463  1.97992  3.37990  4.41866  2.72468  4.05215  2.88390  2.65380  2.44936  2.78930  3.52828  5.81309  3.68713    449 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    239   2.79532  4.56741  2.59886  2.26653  4.72524  2.97326  3.84498  4.20852  1.87988  3.68761  4.42563  2.67816  4.05093  2.72680  2.26697  2.39445  3.11354  3.44147  4.06926  3.70096    450 k - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    240   2.76031  1.91137  4.93344  4.32897  3.47342  4.21043  4.55379  2.12811  4.13437  1.60981  2.11111  4.35327  4.56463  4.27495  4.16872  3.52442  2.73881  2.49904  5.05160  3.88034    451 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    241   3.00579  3.43594  4.91160  4.30236  2.88535  4.17356  4.48924  2.41412  3.62991  0.97514  3.41700  4.31537  4.52645  4.23058  4.12367  3.48482  3.23680  2.59853  2.70167  3.78558    452 l - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    242   2.51291  3.86266  2.42773  2.26878  4.71076  3.65927  3.14908  3.51790  2.32370  3.67561  4.41657  2.44903  4.05255  2.58104  2.64695  2.72413  2.48024  3.27065  5.81133  3.77060    453 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    243   2.89024  4.99098  3.22187  2.69841  3.16242  3.74556  3.43367  3.45008  2.12873  2.47972  3.65551  3.30484  3.00902  2.69329  2.47140  2.87653  2.77051  2.80352  4.74384  3.09104    454 k - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    244   2.75442  4.59220  1.48443  2.55169  4.69407  3.66624  3.85987  4.16899  2.26580  3.66358  4.41104  2.16093  4.06270  2.96232  2.94350  2.69711  3.00639  3.21953  5.80766  4.40610    455 d - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    245   2.53666  4.51809  3.31495  2.50094  3.81458  3.47863  3.66745  3.68842  2.74796  3.30408  3.76297  2.90283  1.45947  2.98944  2.97069  2.84711  3.12065  2.90248  5.56105  4.23506    456 p - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    246   2.18867  5.36299  2.90524  2.21328  4.32931  3.53924  3.49382  3.97251  2.24621  3.14962  3.99253  2.78034  3.78478  2.54072  2.85251  2.30318  2.70173  3.25844  5.80328  3.47734    457 a - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    247   2.48590  4.36945  2.67418  2.22639  4.72760  3.65776  3.84501  4.21118  1.68322  3.11616  4.42723  3.02530  4.05117  2.52411  2.40832  2.54354  2.78662  3.77464  5.82017  4.41136    458 k - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    248   3.97870  5.88109  4.77637  3.79584  5.10245  4.51923  4.26030  4.68907  2.25479  4.07008  4.99673  4.06985  4.83329  3.42182  0.45649  3.98836  4.07883  4.42272  3.45519  4.78623    459 R - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    249   2.59820  4.04607  4.60274  4.00452  3.26886  3.61184  4.36773  2.06089  3.84570  1.56372  3.45362  4.11687  2.06890  4.02734  3.95003  2.68390  3.14561  2.58630  4.40258  3.38622    460 l - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.04987  5.01631  3.16967  0.61958  0.77255  0.48576  0.95510
+    250   2.79362  5.19179  3.01710  2.75300  4.64905  2.77281  4.01085  4.10036  2.79939  3.46822  4.43166  2.61914  4.12461  3.14023  3.27668  1.68833  1.53351  3.69065  5.84113  4.47617    461 t - - T
+          2.68631  4.42192  2.77519  2.73130  3.46353  2.40482  3.72508  3.29367  2.67738  2.69360  4.24703  2.90360  2.73753  3.18148  2.89804  2.37867  2.77518  2.98532  4.58490  3.61498
+          0.12278  2.37863  3.77824  1.17468  0.36950  0.42506  1.06054
+    251   1.47902  3.78300  4.72209  4.11644  2.74562  3.65840  4.38345  2.02614  3.93274  2.07959  3.21794  4.17061  3.49702  4.09137  3.99270  2.98272  3.05871  2.38788  4.48487  3.74373    467 a - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01009  4.99737  5.71972  0.61958  0.77255  0.53813  0.87669
+    252   2.38222  4.71734  2.84513  2.05232  4.42547  3.25385  3.43556  4.19285  2.14440  3.09056  3.51596  2.80436  3.18490  2.67888  2.63294  2.69832  2.67125  3.58577  5.80764  4.40015    468 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01009  4.99737  5.71972  0.61958  0.77255  0.45436  1.00747
+    253   2.65797  4.06542  2.63237  1.57032  4.71890  3.65831  3.45654  4.20087  2.52289  3.68238  4.00276  3.00654  3.59507  2.12286  2.86428  2.58695  3.11362  3.45316  5.81563  3.91003    469 e - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    254   1.93383  3.77543  4.87213  4.26567  3.27005  3.35948  4.48352  1.60295  4.06924  1.71770  3.29328  4.28554  4.50523  4.21524  4.10410  3.45599  3.20183  2.00553  4.99383  3.81574    470 i - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    255   2.91099  3.35807  4.39311  3.80506  3.12662  3.41984  4.32058  2.74098  2.62412  1.35983  2.89439  3.70896  4.38574  3.55146  3.43970  3.02120  3.14303  2.30767  4.99433  3.18557    471 l - - H
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    256   2.62697  4.23577  2.94369  2.01671  4.73311  3.52212  3.12192  4.21804  1.98366  3.41966  4.43054  2.33684  4.05005  2.29561  2.80226  2.65814  2.90658  3.41449  5.82302  4.41298    472 k - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  5.01631  5.73865  0.61958  0.77255  0.48576  0.95510
+    257   2.67425  5.24257  2.69003  2.64384  4.09422  3.68496  1.59772  3.97575  2.52719  3.06621  3.97630  3.17995  4.07682  2.88982  2.86815  2.31165  2.78826  3.60139  5.71188  4.10399    473 h - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.18941  5.01631  1.79622  0.61958  0.77255  0.48576  0.95510
+    258   2.81850  5.23743  2.76502  2.35780  4.54654  3.39495  3.79640  3.57339  2.36240  3.35446  4.28834  3.08690  1.61434  2.83455  2.79066  2.56844  3.04975  3.37601  5.69198  4.30446    474 p - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01183  4.83873  5.56107  0.61958  0.77255  0.86853  0.54398
+    259   3.22678  4.58175  4.94227  4.40609  1.73776  4.31983  4.20406  3.01156  4.21650  2.23279  3.33965  4.33985  4.66520  3.80636  4.24184  3.63704  3.45535  2.61441  1.69956  1.91736    475 w - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01183  4.83873  5.56107  0.61958  0.77255  0.30436  1.33787
+    260   2.99670  4.36610  4.95290  4.33956  1.72799  3.71830  4.50360  1.92619  4.12878  1.69258  2.79907  4.33234  4.52551  4.25179  4.13733  3.48573  3.22794  1.98896  4.25850  3.81122    476 l - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00667  5.01308        *  0.61958  0.77255  0.00000        *
+//
diff --git a/test/jalview/io/test_fn3_hmm.txt b/test/jalview/io/test_fn3_hmm.txt
new file mode 100644 (file)
index 0000000..0dcfa22
--- /dev/null
@@ -0,0 +1,285 @@
+HMMER3/f [3.1b1 | May 2013]
+NAME  fn3
+ACC   PF00041.13
+DESC  Fibronectin type III domain
+LENG  86
+ALPH  amino
+RF    no
+MM    no
+CONS  yes
+CS    yes
+MAP   yes
+DATE  Fri Jun 20 08:22:31 2014
+NSEQ  106
+EFFN  11.415833
+CKSUM 3564431818
+GA    8.00 7.20
+TC    8.00 7.20
+NC    7.90 7.90
+STATS LOCAL MSV       -9.4043  0.71847
+STATS LOCAL VITERBI   -9.7737  0.71847
+STATS LOCAL FORWARD   -3.8341  0.71847
+HMM          A        C        D        E        F        G        H        I        K        L        M        N        P        Q        R        S        T        V        W        Y   
+            m->m     m->i     m->d     i->m     i->i     d->m     d->d
+  COMPO   2.70330  4.91262  3.03272  2.64079  3.60307  2.84344  3.74204  3.07942  2.79841  2.65364  4.14864  2.95826  2.87120  3.02176  2.96125  2.44783  2.59757  2.57680  4.02726  3.21526
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.00000        *
+      1   3.16986  5.21447  4.52134  3.29953  4.34285  4.18764  4.30886  3.35801  3.70246  2.11675  4.32057  4.32984  0.76706  3.91880  4.22437  3.23552  3.21670  2.88223  5.80355  3.93889      1 p - - -
+          2.68629  4.42236  2.77530  2.73088  3.46365  2.40512  3.72505  3.29365  2.67737  2.69316  4.24701  2.90358  2.73734  3.18157  2.89812  2.37898  2.77517  2.98515  4.58488  3.61514
+          0.09796  2.38361  6.81068  0.10064  2.34607  0.48576  0.95510
+      2   2.70230  5.97353  2.24744  2.62947  5.31433  2.60356  4.43584  4.79731  3.17221  2.95090  5.01531  3.26630  2.09873  3.30219  3.34190  1.45782  3.14099  3.57507  6.40877  4.25623      3 s - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+      3   1.38116  5.98285  3.50784  2.54546  5.32790  3.48945  4.43311  4.81385  2.38773  3.98773  5.02352  3.27895  1.92260  2.69012  2.96119  2.64228  3.29228  3.29618  6.41555  4.20553      4 a - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+      4   3.32856  5.10403  4.47046  4.60386  4.23079  4.75438  5.09647  2.69918  4.46632  2.97102  4.23502  4.77984  0.63388  4.68581  3.76781  4.05413  3.46306  2.04533  5.75329  4.56372      5 P - - -
+          2.68616  4.42236  2.77530  2.73134  3.46365  2.40523  3.72505  3.29295  2.67751  2.69303  4.24634  2.90357  2.73739  3.18157  2.89783  2.37897  2.77530  2.98529  4.58488  3.61514
+          0.09682  2.39494  6.81068  0.10162  2.33687  0.48576  0.95510
+      5   2.95325  4.65976  3.57762  2.20709  3.14816  2.51487  3.41109  4.78902  2.65862  3.19599  4.41042  3.45032  3.44719  2.43205  2.26492  2.25400  2.23196  3.66828  4.80003  4.52485      7 e - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01246  6.08833  4.59386  0.61958  0.77255  0.48576  0.95510
+      6   2.74215  5.97618  2.19482  2.69150  4.58171  2.33553  3.83525  3.28222  2.95080  3.32698  5.01691  1.45822  3.52462  2.79670  2.90942  3.13467  3.27956  4.36668  6.40902  3.92307      8 n - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00341  6.07928  6.80162  0.61958  0.77255  0.44282  1.02784
+      7   3.32507  4.98102  3.78072  3.31043  2.85257  4.76439  5.09585  2.50332  4.69760  1.03851  3.36125  4.91001  2.73206  4.83820  4.72389  4.07376  3.83146  1.59790  5.60385  4.42704      9 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.03752  6.08833  3.36505  0.61958  0.77255  0.48576  0.95510
+      8   3.15997  4.90658  3.35204  2.72775  4.53493  3.60960  2.65074  3.69535  2.11078  4.01384  4.99896  3.14668  4.61695  2.40643  2.34723  1.92358  2.03982  3.05153  6.39127  4.98082     10 s - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00349  6.05430  6.77664  0.61958  0.77255  0.35749  1.20207
+      9   1.76295  3.98252  5.55061  4.93551  2.13202  3.39992  5.09294  2.14638  4.23898  2.23988  3.42109  4.92079  4.39252  3.70640  3.99349  3.50811  3.63432  1.47830  4.51148  4.41177     11 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     10   3.01387  4.98892  2.91217  2.42744  5.22342  4.00576  3.74074  2.67275  2.47618  2.92529  3.89570  3.36720  4.15809  3.26810  2.80854  1.81572  2.02040  2.77133  4.92415  4.31555     12 s - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     11   2.41247  5.98374  2.24093  2.04842  3.41543  2.59695  4.10033  4.81544  3.05501  4.28918  5.02429  2.22829  2.90635  3.12939  3.01921  2.37278  3.01194  3.02522  6.41619  3.66635     13 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.06784  6.08833  2.75947  0.61958  0.77255  0.48576  0.95510
+     12   2.77725  4.36386  3.23435  2.92496  4.75140  4.31852  4.53101  1.91389  3.01135  2.51491  3.47932  2.97934  3.54432  2.88257  2.68923  3.07794  2.71169  1.80880  6.06849  4.75973     14 v - - E
+          2.68623  4.42259  2.77533  2.73059  3.46323  2.40500  3.72529  3.29333  2.67757  2.69369  4.24724  2.90364  2.73744  3.18108  2.89835  2.37891  2.77531  2.98493  4.58511  3.61510
+          0.22113  1.62346  6.74643  0.44471  1.02446  0.29166  1.37446
+     13   3.17575  5.97994  3.10322  2.84738  5.32369  2.00173  4.43389  4.80873  3.01150  3.75019  4.42663  2.23751  4.64014  2.74467  2.85546  1.99984  1.67133  4.36987  5.08444  3.58488     18 t - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     14   2.14203  5.98483  2.53686  2.20884  5.33077  2.76253  3.61799  4.81737  2.91636  3.96256  5.02525  2.79307  2.44932  3.35978  3.34773  1.76758  2.51815  4.12754  4.53404  4.35768     19 s - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02274  6.08833  3.90154  0.61958  0.77255  0.48576  0.95510
+     15   3.45984  5.96297  2.32904  2.98671  5.30486  3.14893  3.59992  3.68067  2.95954  4.26690  5.00447  2.01875  4.62814  3.51950  2.89162  1.97303  1.47565  3.87160  6.39755  3.59993     20 t - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00344  6.06904  6.79138  0.61958  0.77255  0.40302  1.10352
+     16   2.82603  5.98256  2.96292  2.53617  4.39559  3.14388  4.09532  4.81336  2.59005  4.28779  5.02326  3.12547  4.63955  2.76620  3.03618  1.28432  2.14874  3.55065  4.82032  3.29405     21 s - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     17   2.29842  4.96481  5.56794  4.95172  2.45211  3.33868  4.31545  1.97312  4.73378  1.34355  2.88087  4.92903  5.12608  4.86259  4.73754  4.07438  3.55674  1.71344  5.58685  3.78328     22 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     18   2.99930  4.68496  3.44656  2.53427  3.92510  4.04338  3.13178  3.10095  3.07007  2.68343  3.58599  3.17010  4.15335  2.63450  2.71950  2.30083  2.03779  2.23518  4.92400  3.84991     23 t - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     19   3.61302  4.50726  5.99163  5.39935  2.74200  5.23506  5.61087  1.85210  5.20622  1.10188  3.56291  5.40353  5.56305  5.33364  5.22134  4.56441  3.85751  1.20867  6.05610  4.88933     24 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     20   2.90508  5.98486  3.37356  2.37027  5.33083  3.46854  3.40789  4.81743  2.65230  3.22177  4.17825  2.67373  4.63906  2.52648  2.39431  1.50547  2.16764  4.37598  5.01440  5.00552     25 s - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     21   5.54218  6.63564  6.83891  6.61797  2.57168  6.35073  5.30532  3.96643  6.37377  3.18917  5.26281  6.07009  4.35269  6.11992  6.21105  5.74680  5.75143  4.86346  0.24436  3.66807     26 W - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     22   3.10862  5.98423  2.61761  2.10221  4.46995  3.93009  3.84182  3.79843  2.19229  3.09373  4.47555  2.66452  4.06864  2.59255  2.99987  1.99073  2.05618  3.67318  6.41655  4.47364     27 s - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     23   2.05280  5.87614  3.77610  2.63103  5.17655  3.25143  3.55897  3.09279  2.68152  3.35866  4.92882  3.43937  1.44938  3.29932  2.98336  2.85751  2.78420  3.02863  4.43359  4.47040     28 p - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     24   2.65644  5.88726  3.37601  2.96202  5.19190  3.53629  4.46143  4.20046  2.87295  2.91429  4.93884  3.27084  1.07653  3.39095  3.69926  2.07705  3.29723  2.92337  6.34501  4.95985     29 p - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.32165  6.08833  1.29911  0.61958  0.77255  0.48576  0.95510
+     25   2.44244  5.77880  2.64467  2.21733  3.20572  3.66340  3.27861  4.60939  2.17717  2.95495  4.81953  3.17778  2.62084  2.96028  2.64039  2.55818  2.51134  3.52175  6.21164  4.20060     30 k - - S
+          2.68557  4.42278  2.77404  2.73101  3.46370  2.40555  3.72548  3.29364  2.67779  2.69337  4.24743  2.90378  2.73741  3.18051  2.89835  2.37928  2.77557  2.98526  4.58530  3.61392
+          1.12909  0.74203  1.60680  0.24883  1.51281  1.67198  0.20810
+     26   2.76497  5.64634  2.06362  2.44254  4.06108  3.91520  3.28362  3.73992  2.46695  3.95074  4.68755  2.93859  2.87257  2.71813  3.08100  2.16767  2.28242  3.00778  6.08028  4.00221     33 d - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00580  5.54941  6.27176  0.61958  0.77255  1.23854  0.34222
+     27   2.94904  4.81418  2.88265  2.99332  4.83563  1.49306  3.87927  3.68299  2.59086  2.53757  4.07313  2.89409  2.92833  3.04624  2.88166  2.82744  3.22994  3.21444  4.18838  4.04981     34 g - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00508  5.68074  6.40309  0.61958  0.77255  0.20085  1.70396
+     28   2.96588  5.95917  2.45759  2.65943  5.30490  1.91234  3.11781  3.44164  2.78003  4.01788  4.99965  2.12379  3.26764  2.84040  2.87160  2.26272  3.15721  3.84740  4.86821  3.64128     35 g - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00351  6.05095  6.77330  0.61958  0.77255  0.34864  1.22298
+     29   2.45969  5.96445  2.88574  2.61716  5.30131  1.53630  4.43818  3.46883  2.98393  3.60366  4.33332  3.25719  4.28257  3.08417  2.40821  2.08539  3.20111  2.81105  6.40207  4.25093     36 g - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     30   2.71563  5.98438  2.50720  1.96228  5.33013  3.47246  3.38617  3.68065  2.34086  4.03521  4.36775  3.08029  1.87041  2.90329  3.33287  2.70645  2.77558  2.97286  6.41666  4.17777     37 p - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     31   3.04837  4.96747  2.67316  4.92527  2.42064  4.14655  5.09097  1.34551  4.71334  2.18068  3.34829  4.91585  3.31178  4.15082  4.72663  3.69906  3.53551  1.88881  3.93067  3.04034     38 i - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     32   2.89418  4.58676  2.12720  2.65970  3.99748  4.30700  4.50689  3.12934  2.75241  2.32504  4.34805  3.25317  4.69765  2.93544  2.97945  2.48570  1.85268  2.60501  5.05387  4.40931     39 t - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     33   3.05045  5.96458  3.15002  2.79713  4.16491  1.56242  3.20986  4.07540  2.34002  3.77648  3.66616  2.65073  4.64351  3.21500  2.62101  2.34442  2.98761  3.25677  5.04578  3.36446     40 g - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     34   4.72855  5.99332  6.32397  5.91516  1.75259  5.71064  3.47111  3.64093  3.68669  3.44300  5.13564  5.60513  6.03397  5.64902  5.63703  5.05114  4.95149  3.46344  3.97019  0.49348     41 Y - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     35   3.03913  5.98101  2.74983  1.95825  3.75604  3.98121  3.78677  3.48894  2.41418  2.89991  5.02189  2.66693  4.63989  2.65222  2.20113  2.26435  2.64729  3.16844  6.41420  3.93691     42 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     36   3.75576  5.90373  6.92143  6.48083  5.27028  6.48043  7.33031  1.16190  6.46559  1.72148  4.18143  6.65320  6.63807  6.70678  6.63399  5.94811  5.00240  0.82398  7.51298  6.31097     43 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.04904  6.08833  3.08806  0.61958  0.77255  0.48576  0.95510
+     37   2.63429  4.71789  2.89387  2.04081  4.17861  4.22097  3.38514  2.92734  2.36124  3.26230  4.97143  3.69265  4.61418  2.27063  2.38238  2.70982  2.11937  3.37005  6.36711  3.73375     44 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00353  6.04282  6.76517  0.61958  0.77255  0.32899  1.27173
+     38   3.00800  2.48193  5.53105  4.91728  2.98458  4.75707  4.15268  2.83469  3.12355  2.32451  4.08737  4.91198  5.12099  4.84273  3.46182  3.58557  3.26283  2.28912  2.64554  1.29971     45 y - - E
+          2.68641  4.42053  2.77543  2.73091  3.46377  2.40536  3.72420  3.29377  2.67764  2.69378  4.24582  2.90336  2.73763  3.18113  2.89660  2.37910  2.77543  2.98542  4.58500  3.61526
+          0.12278  2.16768  6.81068  0.54422  0.86820  0.48576  0.95510
+     39   2.52553  4.02469  3.60093  2.65311  4.18239  3.63052  4.17989  3.44209  2.14970  3.12319  4.96260  3.43770  4.02454  2.12722  2.15391  2.32250  3.25888  3.40611  2.73453  3.57446     49 q - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02932  6.08833  3.62591  0.61958  0.77255  0.48576  0.95510
+     40   2.85303  5.96779  2.74660  1.91867  5.31393  3.60453  3.59476  4.33679  2.36399  3.57280  3.62613  2.83996  2.06170  2.51716  3.24767  2.43993  2.61505  3.39964  6.39984  4.98824     50 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00347  6.06248  6.78482  0.61958  0.77255  0.67944  0.70705
+     41   2.55267  3.11480  2.72137  2.31006  5.21613  3.67111  4.08491  3.18721  2.11932  2.73126  3.73119  3.72342  3.44703  2.78931  3.31632  2.60923  2.50487  2.33623  6.34948  4.95631     51 k - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.09789  6.06248  2.39773  0.61958  0.77255  0.38130  1.14877
+     42   3.41114  5.92195  2.00739  2.51445  4.35946  1.85149  4.04885  4.75310  3.02073  3.41727  4.96259  1.88803  4.57836  2.81891  2.77402  2.53317  2.79169  3.60394  6.35459  4.48731     52 g - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00370  5.99676  6.71911  0.61958  0.77255  0.25112  1.50474
+     43   2.89692  5.98568  2.39354  2.04021  5.33202  2.12548  3.27810  4.81889  2.36649  3.39071  4.58505  2.82477  4.63888  2.99231  3.02264  2.04514  2.45319  3.82791  6.41761  5.00590     53 e - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     44   3.10206  5.95088  3.50928  2.19657  4.70794  1.83640  4.44201  3.85177  2.81849  3.20653  3.64542  2.17673  2.82486  2.50236  3.67274  2.64718  2.71954  3.18909  6.39210  3.73228     54 g - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.08059  6.08833  2.58819  0.61958  0.77255  0.48576  0.95510
+     45   2.83017  5.93388  2.31048  1.94273  5.28007  2.46456  3.60606  4.35357  2.35448  2.95362  4.97424  3.06816  3.41033  2.69285  2.84649  2.21743  2.98206  3.67978  4.23187  4.95426     55 e - - C
+          2.68733  4.40831  2.77609  2.73043  3.46444  2.40393  3.72592  3.29278  2.67833  2.69426  4.24827  2.90407  2.73626  3.18024  2.89744  2.37952  2.77650  2.98614  4.58019  3.61570
+          1.45631  0.90375  1.01651  1.51529  0.24813  0.96821  0.47765
+     46   2.32839  5.42660  2.93163  2.28220  4.02543  3.04571  3.03894  3.22247  2.82753  3.21315  3.89864  3.49093  2.50859  3.14260  2.89921  2.69284  3.05772  2.38519  4.38264  3.20345     66 e - - G
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00571  5.56406  6.28641  0.61958  0.77255  0.18459  1.78051
+     47   2.69465  3.91083  2.42967  2.34662  4.43247  3.13708  3.62175  3.49809  2.56727  2.84127  4.03266  3.52527  3.00745  3.22895  3.52756  2.46523  2.69768  3.11906  2.19019  4.92515     67 w - - C
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00353  6.04443  6.76678  0.61958  0.77255  0.33269  1.26228
+     48   2.67627  5.86490  3.17099  3.22595  3.40616  4.27494  3.15476  3.07365  2.21494  2.78239  4.39426  2.30764  3.56160  2.19351  2.71433  2.94392  2.62330  2.55032  5.16850  4.37026     68 q - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     49   3.05871  5.98132  3.36643  1.71285  5.32569  3.90513  2.27648  4.25125  2.92072  4.28630  4.28595  2.90579  3.33969  2.79371  2.63337  2.42582  2.46361  2.81009  3.46671  3.72048     69 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     50   2.88323  4.65127  3.40086  2.73607  2.41972  3.62669  3.91044  2.52424  2.75640  2.37424  3.94274  3.64921  4.76561  2.38668  2.64750  3.03028  3.09193  2.27100  6.08057  3.03402     70 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     51   3.36533  5.95840  2.65995  2.86095  3.44584  4.25167  3.55888  2.90987  2.78397  3.33346  3.90493  2.03375  3.68901  2.80089  2.78508  2.11531  1.97302  3.15541  6.39763  4.99330     71 t - - E
+          2.68571  4.42246  2.77540  2.73144  3.46375  2.40497  3.72515  3.29375  2.67742  2.69376  4.24711  2.90367  2.73710  3.18135  2.89822  2.37876  2.77540  2.98457  4.58498  3.61524
+          0.06628  2.76409  6.81068  0.97562  0.47314  0.48576  0.95510
+     52   2.38926  5.49703  3.09615  2.80044  4.68202  3.76562  4.62096  2.19958  3.33274  2.03099  4.11871  2.97731  4.26404  3.83080  2.89542  3.19964  2.84193  1.56133  6.03936  4.75239     75 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     53   2.79501  4.92737  2.35659  2.60299  4.06511  2.98090  3.88301  4.80087  2.44593  3.57653  5.01701  3.37711  1.76863  3.53250  3.23955  1.94419  2.68524  2.95506  6.41016  5.00121     76 p - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     54   2.44542  5.98316  3.18675  2.55065  5.32835  2.12386  4.43300  4.38419  2.38413  2.93654  5.02378  2.50193  2.49139  3.27226  2.05133  2.36069  3.70337  4.12664  4.32391  4.48343     77 r - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     55   2.77179  5.98329  2.50848  2.76644  5.32854  3.30269  3.08416  4.38434  3.16759  4.28865  5.02390  2.27915  2.67265  2.61285  3.32102  2.18277  1.82444  2.83013  6.41587  4.35727     78 t - - T
+          2.68621  4.42251  2.77546  2.73149  3.46380  2.40468  3.72521  3.29380  2.67767  2.69252  4.24716  2.90344  2.73766  3.18134  2.89827  2.37913  2.77442  2.98545  4.58503  3.61529
+          0.07130  2.69245  6.81068  1.11635  0.39671  0.48576  0.95510
+     56   2.32530  5.97446  3.57954  1.89562  5.31575  4.24796  3.32554  3.73278  2.42253  2.98562  5.01611  3.71687  3.10116  2.71107  2.91871  2.60336  1.70360  3.15915  6.40941  5.00074     83 t - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.35248  6.08833  1.22151  0.61958  0.77255  0.48576  0.95510
+     57   2.95924  5.72336  2.75932  2.63159  3.96190  3.29462  3.22449  3.40062  2.77057  3.18108  3.56769  2.46117  2.98702  3.05715  2.72729  2.56520  1.96589  3.52719  6.16591  2.96938     84 t - - S
+          2.68622  4.42162  2.77539  2.73088  3.46349  2.40510  3.72514  3.29311  2.67761  2.69358  4.24710  2.90367  2.73759  3.18166  2.89753  2.37894  2.77488  2.98538  4.58497  3.61523
+          0.23969  1.55321  6.46298  0.15973  1.91309  0.51157  0.91517
+     58   2.78411  5.86726  3.65151  2.46190  3.55121  3.32277  3.71415  3.82816  2.87545  3.69015  4.27003  2.90512  3.60994  2.68731  2.37548  1.72361  1.95655  3.42914  6.30822  3.85760     87 s - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00384  5.96109  6.68344  0.61958  0.77255  0.21363  1.64843
+     59   2.13080  3.38910  5.56698  4.95075  2.41578  4.20194  3.39215  2.83299  4.73282  2.14660  3.19234  4.92810  5.12527  4.86169  4.18461  4.07348  3.03808  1.63705  4.66089  1.78369     88 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     60   3.12543  5.93769  2.99354  2.53954  5.26303  4.25659  3.21054  2.85212  2.62935  2.82513  3.45830  2.90110  4.19559  2.80624  3.10357  2.88568  1.50190  2.67316  6.38237  3.93622     89 t - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     61   3.61965  4.99402  3.63828  4.95783  2.26826  4.79135  5.12555  1.86647  4.74679  1.34194  3.74460  4.94944  5.15281  3.10559  4.75989  3.74420  3.85186  1.42486  5.61987  4.44474     90 l - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     62   3.10387  5.98366  3.06368  2.31445  4.05906  3.57903  3.48488  4.81531  2.43543  4.01680  3.91148  2.67498  2.99920  2.70828  2.56621  2.14984  1.90367  3.06274  4.55677  4.37671     91 t - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     63   3.34220  5.98744  1.86090  2.69096  5.33359  1.40608  3.63608  4.82043  2.48624  4.29318  4.45099  1.96888  4.06897  3.19339  3.48838  2.73868  3.70514  4.37867  6.41942  4.25681     92 g - - S
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     64   5.18530  6.36522  4.58586  6.57578  3.53131  6.59442  6.84537  2.81242  6.44067  0.21363  3.54046  6.78308  6.53953  6.19263  6.31583  5.99910  5.37457  3.39834  6.73440  5.83217     93 L - - -
+          2.68590  4.42227  2.77521  2.73125  3.46356  2.40515  3.72496  3.29356  2.67743  2.69357  4.24692  2.90349  2.73741  3.18148  2.89803  2.37889  2.77521  2.98520  4.58479  3.61505
+          0.02033  3.96193  6.81068  0.31431  1.31041  0.48576  0.95510
+     65   2.93361  5.98253  3.16620  2.07447  5.32745  3.84017  3.84639  3.52003  2.07989  2.71701  4.56317  3.05465  3.94228  2.39023  2.13660  2.81003  2.42767  2.98359  6.41531  3.87097     95 e - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     66   2.17452  5.85112  3.79178  2.44872  5.14174  4.27993  4.47388  4.59086  3.04069  4.13287  4.42378  3.36057  0.82761  3.31072  3.71538  3.13243  3.15654  3.97958  4.90439  4.38214     96 p - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     67   2.72531  5.97666  2.50761  2.79752  4.22378  1.29966  2.70734  4.80294  2.85170  4.02964  5.01805  2.59981  4.64085  3.32835  3.25617  2.51345  3.59137  3.91820  4.88800  2.97800     97 g - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     68   2.39925  4.86641  3.79312  2.74568  5.13568  4.27988  3.97435  3.95098  2.69562  3.65359  3.00813  3.38952  4.67180  3.12070  2.33490  2.43668  1.27713  2.90106  6.31421  4.93977     98 t - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     69   2.87821  5.98261  2.71299  2.05681  3.93787  3.36966  3.57296  3.81023  2.25993  3.03102  3.49917  2.39917  3.09415  2.62154  2.82818  2.67359  2.51409  3.67730  4.58228  5.00448     99 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     70   6.32206  7.09639  6.95855  7.01624  2.70399  6.62558  5.12529  5.84365  6.77161  4.03604  6.32463  4.32154  6.86163  6.30239  6.48747  6.05185  6.49899  5.81871  5.18730  0.14189    100 Y - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     71   3.06725  5.97020  3.56838  1.93769  4.23056  3.77167  3.39655  3.53252  2.56448  3.45405  4.47893  2.47898  4.64226  2.55695  2.74362  2.36648  2.01401  2.66399  6.40629  3.70776    101 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     72   3.19486  4.19171  5.58508  4.96942  1.44027  4.15574  5.11433  1.81297  4.75161  2.09873  3.37140  4.94615  5.14143  4.88008  4.75485  4.09123  3.83769  1.47173  5.60267  3.09551    102 f - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     73   3.18039  4.06436  3.15201  2.27681  5.32468  3.77041  3.95744  3.70705  2.23538  4.28548  4.11883  2.88564  4.63997  2.58030  1.70576  2.27707  2.39981  3.62914  4.03739  3.61343    103 r - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     74   3.76685  5.84337  6.79391  6.31497  3.84743  6.27452  6.95358  1.59565  6.25134  2.11498  4.30213  6.44619  6.46746  6.44080  6.36566  5.70153  4.90672  0.53161  7.20703  6.03175    104 V - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     75   2.31005  4.88319  3.40675  2.63903  3.58848  4.26911  3.49342  3.09105  2.39543  3.00463  4.93879  3.41670  4.66153  1.98639  2.22144  3.11070  2.61129  2.78609  6.34491  2.92043    105 q - - E
+          2.68621  4.42228  2.77522  2.73126  3.46357  2.40516  3.72497  3.29357  2.67744  2.69312  4.24693  2.90350  2.73743  3.18149  2.89804  2.37890  2.77522  2.98521  4.58480  3.61506
+          0.03738  3.58894  4.70319  0.25135  1.50394  0.48576  0.95510
+     76   0.79499  5.17226  4.80437  3.93376  4.33120  3.17569  4.96596  3.30029  4.15773  2.86829  4.32533  4.52823  5.01384  4.41886  4.42465  2.28661  2.19420  2.76335  5.81537  4.60940    107 a - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00340  6.08033  6.80268  0.61958  0.77255  0.44741  1.01966
+     77   2.84306  4.15407  4.98296  3.19564  3.23517  4.66606  3.67524  2.49603  3.23224  2.21212  3.84796  4.62630  5.03633  2.88555  2.43211  3.49088  3.22704  1.33993  5.67363  2.88123    108 v - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     78   3.27061  4.75060  2.81965  3.10410  5.31934  3.95942  3.99367  3.88107  2.62205  4.02823  5.01830  1.35628  3.08534  3.32913  3.08546  1.88067  2.21938  4.02145  6.41122  3.76470    109 n - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00992  6.08833  4.87890  0.61958  0.77255  0.48576  0.95510
+     79   2.39836  4.69624  2.57939  2.56364  4.72011  1.55094  3.74815  4.26504  2.61409  4.28517  5.02018  2.82673  4.26340  2.69971  2.87382  2.73983  2.53993  3.07568  6.41202  5.00074    110 g - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00340  6.08180  6.80415  0.61958  0.77255  0.45398  1.00812
+     80   2.22211  4.94595  2.69424  2.44928  4.84552  2.32005  3.06335  2.95704  2.33976  3.55821  4.09648  2.87488  4.09930  2.85656  2.97877  3.08279  3.07714  2.39346  6.40553  4.01548    111 a - - T
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.38398  6.08833  1.15015  0.61958  0.77255  0.48576  0.95510
+     81   2.96920  5.43248  3.46409  2.76236  3.93019  1.02513  4.29951  4.07917  3.10833  3.39330  4.50784  3.40559  4.48149  3.45547  3.56956  2.50552  2.39680  3.76237  5.94228  3.01765    112 g - - E
+          2.68652  4.42259  2.77488  2.73144  3.46170  2.40466  3.72529  3.29388  2.67703  2.69373  4.24724  2.90335  2.73774  3.18162  2.89801  2.37895  2.77529  2.98552  4.58511  3.61537
+          0.29928  1.35852  6.43163  0.48724  0.95274  1.77816  0.18506
+     82   2.84273  4.18992  3.05053  2.12883  3.36284  2.75189  4.25559  3.03507  2.66396  2.65563  4.59024  2.63081  3.84786  2.76844  3.19058  2.84597  2.82776  2.89016  3.06821  3.41272    117 e - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00494  5.70928  6.43163  0.61958  0.77255  1.56406  0.23482
+     83   3.37920  5.61493  3.74277  3.20384  4.92800  1.01625  3.96683  4.35082  2.94708  2.91738  4.72998  3.71516  3.70329  3.52945  3.00683  1.61777  3.61882  4.00263  6.13360  4.80162    118 g - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00481  5.73459  6.45693  0.61958  0.77255  0.30535  1.33510
+     84   2.58463  5.93784  3.04102  2.09605  4.57465  2.51630  3.24109  4.26208  2.60545  3.44607  3.62705  3.20484  1.89678  2.68661  2.74662  2.97880  3.02092  3.23569  6.37074  4.50367    119 p - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00361  6.02233  6.74467  0.61958  0.77255  0.28862  1.38348
+     85   2.48488  5.72055  3.87501  1.97538  3.04853  3.48010  4.51877  3.51898  2.88839  2.73568  4.42660  3.64380  2.08811  3.48814  2.70856  2.40769  2.92982  4.05679  2.77386  3.43366    120 e - - B
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00338  6.08833  6.81068  0.61958  0.77255  0.48576  0.95510
+     86   3.03720  5.94099  3.75455  2.96917  5.26587  2.91682  3.66571  4.11840  2.98472  4.23738  4.98891  3.74380  4.66031  3.40955  3.12788  0.72443  2.46104  4.32115  6.38683  4.99111    121 s - - E
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00227  6.08723        *  0.61958  0.77255  0.00000        *
+//
index 1687516..d01e53f 100644 (file)
@@ -22,6 +22,7 @@ package jalview.renderer;
 
 import static org.testng.AssertJUnit.assertEquals;
 
+import jalview.api.AlignViewportI;
 import jalview.bin.Cache;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
@@ -33,6 +34,7 @@ import jalview.gui.JvOptionPane;
 import jalview.schemes.ColourSchemeI;
 import jalview.schemes.UserColourScheme;
 import jalview.schemes.ZappoColourScheme;
+import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.Color;
 import java.util.ArrayList;
@@ -56,7 +58,7 @@ public class OverviewResColourFinderTest
   {
     SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
     AlignmentI al = new Alignment(new SequenceI[] { seq });
-    final AlignViewport av = new AlignViewport(al);
+    final AlignViewportI av = new AlignViewport(al);
     ResidueColourFinder rcf = new OverviewResColourFinder();
 
     // gaps are grey, residues white
@@ -80,7 +82,7 @@ public class OverviewResColourFinderTest
     SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
                                                             // gap
     AlignmentI al = new Alignment(new SequenceI[] { seq });
-    final AlignViewport av = new AlignViewport(al);
+    final AlignViewportI av = new AlignViewport(al);
     ResidueColourFinder rcf = new OverviewResColourFinder();
     av.setGlobalColourScheme(new ZappoColourScheme());
 
@@ -126,7 +128,7 @@ public class OverviewResColourFinderTest
     SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
                                                             // gap
     AlignmentI al = new Alignment(new SequenceI[] { seq });
-    final AlignViewport av = new AlignViewport(al);
+    final AlignViewportI av = new AlignViewport(al);
     ResidueColourFinder rcf = new OverviewResColourFinder();
 
     Color[] newColours = new Color[24];
@@ -179,7 +181,7 @@ public class OverviewResColourFinderTest
     SequenceGroup[] groups = new SequenceGroup[1];
     groups[0] = sg;
     
-    final AlignViewport av = new AlignViewport(al);
+    final AlignViewportI av = new AlignViewport(al);
     ResidueColourFinder rcf = new OverviewResColourFinder();
     
     // G in group specified as magenta in Zappo
@@ -230,8 +232,6 @@ public class OverviewResColourFinderTest
   {
     SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
                                                             // gap
-    AlignmentI al = new Alignment(new SequenceI[] { seq });
-    final AlignViewport av = new AlignViewport(al);
 
     // non-legacy colouring
     ResidueColourFinder rcf = new OverviewResColourFinder();
@@ -269,9 +269,7 @@ public class OverviewResColourFinderTest
 
     // gaps gap colour
     c = rcf.getBoxColour(shader, seq, 3);
-    assertEquals(
-            jalview.renderer.OverviewResColourFinder.OVERVIEW_DEFAULT_GAP,
-            c);
+    assertEquals(OverviewResColourFinder.OVERVIEW_DEFAULT_GAP, c);
 
     // non legacy colouring with colour scheme
     rcf = new OverviewResColourFinder(false, Color.blue, Color.red);
index 81fb2c0..24f653c 100644 (file)
@@ -22,6 +22,7 @@ package jalview.renderer;
 
 import static org.testng.AssertJUnit.assertEquals;
 
+import jalview.api.AlignViewportI;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Sequence;
@@ -30,6 +31,7 @@ import jalview.gui.AlignViewport;
 import jalview.gui.JvOptionPane;
 import jalview.schemes.UserColourScheme;
 import jalview.schemes.ZappoColourScheme;
+import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.Color;
 
@@ -51,7 +53,7 @@ public class ResidueColourFinderTest
   {
     SequenceI seq = new Sequence("name", "MATVLGSPRAPAFF"); // FER1_MAIZE...
     AlignmentI al = new Alignment(new SequenceI[] { seq });
-    final AlignViewport av = new AlignViewport(al);
+    final AlignViewportI av = new AlignViewport(al);
     ResidueColourFinder rcf = new ResidueColourFinder();
     av.setGlobalColourScheme(new ZappoColourScheme());
 
@@ -86,7 +88,7 @@ public class ResidueColourFinderTest
   {
     SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
     AlignmentI al = new Alignment(new SequenceI[] { seq });
-    final AlignViewport av = new AlignViewport(al);
+    final AlignViewportI av = new AlignViewport(al);
     ResidueColourFinder rcf = new ResidueColourFinder();
 
     assertEquals(Color.white,
@@ -109,7 +111,7 @@ public class ResidueColourFinderTest
     SequenceI seq = new Sequence("name", "MAT--GSPRAPAFF"); // FER1_MAIZE... + a
                                                             // gap
     AlignmentI al = new Alignment(new SequenceI[] { seq });
-    final AlignViewport av = new AlignViewport(al);
+    final AlignViewportI av = new AlignViewport(al);
     ResidueColourFinder rcf = new ResidueColourFinder();
 
     Color[] newColours = new Color[24];
index 0af67cd..e78fc5a 100644 (file)
@@ -6,10 +6,10 @@ import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
 import jalview.gui.AlignFrame;
-import jalview.gui.AlignViewport;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
 import jalview.renderer.ScaleRenderer.ScaleMark;
+import jalview.viewmodel.AlignmentViewport;
 
 import java.util.List;
 
@@ -23,7 +23,7 @@ public class ScaleRendererTest
     String data = ">Seq/20-45\nABCDEFGHIJKLMNOPQRSTUVWXYS\n";
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(data,
             DataSourceType.PASTE);
-    AlignViewport av = af.getViewport();
+    AlignmentViewport av = af.getViewport();
 
     /*
      * scale has minor ticks at 5, 15, 25, major at 10 and 20
index d8b905e..76e4fc5 100644 (file)
@@ -6,11 +6,11 @@ import static org.testng.Assert.assertNotEquals;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
+import jalview.api.AlignViewportI;
 import jalview.api.FeatureColourI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
-import jalview.gui.AlignViewport;
 import jalview.gui.FeatureRenderer;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
@@ -43,7 +43,7 @@ import org.testng.annotations.Test;
  */
 public class FeatureColourFinderTest
 {
-  private AlignViewport av;
+  private AlignViewportI av;
 
   private SequenceI seq;
 
index d35ca76..af7036f 100644 (file)
@@ -85,8 +85,6 @@ public class ClustalxColourSchemeTest
 
     // TODO more test cases; check if help documentation matches implementation
   }
-
-  // @formatter:on
   
   /**
    * Test for colour calculation when the consensus percentage ignores gapped
diff --git a/test/jalview/schemes/HmmerGlobalBackgroundTest.java b/test/jalview/schemes/HmmerGlobalBackgroundTest.java
new file mode 100644 (file)
index 0000000..1cdee91
--- /dev/null
@@ -0,0 +1,90 @@
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.io.DataSourceType;
+import jalview.io.HMMFile;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import org.testng.annotations.Test;
+
+public class HmmerGlobalBackgroundTest {
+
+  @Test(groups = "Functional")
+  public void testFindColour() throws MalformedURLException, IOException
+  {
+    HMMFile file = new HMMFile("test/jalview/io/test_PKinase_hmm.txt",
+            DataSourceType.FILE);
+
+    SequenceI hmmSeq = file.getSeqsAsArray()[0];
+    AlignmentI al = new Alignment(new SequenceI[] { hmmSeq });
+    ColourSchemeI scheme = new HmmerGlobalBackground(al);
+
+    /*
+     * 'A' in column 1, node 2, match emission 2.77204
+     * e-2.77204 = 0.0625 
+     * background frequency is 0.0826
+     * ratio is 0.757, log is negative, colour is Orange
+     */
+    Color actual = scheme.findColour('A', 1, null, null, 0);
+    assertEquals(actual, Color.ORANGE);
+
+    // gap is white
+    actual = scheme.findColour('-', 2, null, null, 0);
+    assertEquals(actual, Color.WHITE);
+    actual = scheme.findColour(' ', 2, null, null, 0);
+    assertEquals(actual, Color.WHITE);
+    actual = scheme.findColour('.', 2, null, null, 0);
+    assertEquals(actual, Color.WHITE);
+
+    /*
+     * 'Y' in column 4, node 5, match emission 4.41426
+     * e-4.41426 = 0.0121 
+     * background frequency is 0.0292
+     * ratio is 0.414, log is negative, colour is Orange
+     */
+    actual = scheme.findColour('Y', 4, null, null, 0);
+    assertEquals(actual, Color.ORANGE);
+
+    /*
+     * 'M' in column 109, no matching node, colour is reddish
+     */
+    actual = scheme.findColour('M', 109, null, null, 0);
+    assertEquals(actual, new Color(230, 0, 0));
+
+    /*
+     * 'I' in column 6, node 7, match emission 1.33015
+     * e-1.33015 = 0.2644
+     * background frequency is 0.0593
+     * ratio is 4.459, log is 1.495
+     * colour is graduated 1.495/4.52 or 84/255 of the way from
+     * white(255, 255, 255) to blue(0, 0, 255)
+     */
+    actual = scheme.findColour('I', 6, null, null, 0);
+    assertEquals(actual, new Color(171, 171, 255));
+
+    /*
+     * 'V' in column 14, node 15, match emission 0.44769
+     * e-0.44769 = 0.6391
+     * background frequency is 0.0686
+     * ratio is 9.316, log is 2.232
+     * colour is graduated 2.232/4.52 or 126/255 of the way from
+     * white(255, 255, 255) to blue(0, 0, 255)
+     */
+    actual = scheme.findColour('V', 14, null, null, 0);
+    assertEquals(actual, new Color(129, 129, 255));
+
+    /*
+     * invalid symbol is White
+     */
+    actual = scheme.findColour('X', 2, null, null, 0);
+    assertEquals(actual, Color.WHITE);
+  }
+
+}
diff --git a/test/jalview/schemes/HmmerLocalBackgroundTest.java b/test/jalview/schemes/HmmerLocalBackgroundTest.java
new file mode 100644 (file)
index 0000000..5f2bb8f
--- /dev/null
@@ -0,0 +1,77 @@
+package jalview.schemes;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.io.DataSourceType;
+import jalview.io.HMMFile;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import org.testng.annotations.Test;
+
+public class HmmerLocalBackgroundTest {
+
+  @Test(groups = "Functional")
+  public void testFindColour() throws MalformedURLException, IOException
+  {
+    HMMFile file = new HMMFile("test/jalview/io/test_PKinase_hmm.txt",
+            DataSourceType.FILE);
+
+    /*
+     * alignment with 20 residues and background frequencies:
+     * A/a, S 3/20 = 0.15
+     * M, K 4/20 = 0.2
+     * V 2/20 = 0.1
+     * Q, R, L 1/20 = 0.05
+     * log(totalCount) = log(20) = 2.996
+     */
+    SequenceI seq1 = new Sequence("seq1", "AAMMMKKKVV");
+    SequenceI seq2 = new Sequence("seq2", "aAM-QKRSSSL");
+    SequenceI hmmSeq = file.getSeqsAsArray()[0];
+    AnnotatedCollectionI ac = new Alignment(
+            new SequenceI[]
+            { hmmSeq, seq1, seq2 });
+    ColourSchemeI scheme = new HmmerLocalBackground(ac);
+
+    /*
+     * 'A' in column 1, node 2, match emission 2.77204
+     * e-2.77204 = 0.0625 
+     * background frequency is 0.15
+     * ratio is < 1, log is negative, colour is Orange
+     */
+    Color actual = scheme.findColour('A', 1, null, null, 0);
+    assertEquals(actual, Color.ORANGE);
+
+    // gap is white
+    actual = scheme.findColour('-', 2, null, null, 0);
+    assertEquals(actual, Color.WHITE);
+    actual = scheme.findColour(' ', 2, null, null, 0);
+    assertEquals(actual, Color.WHITE);
+    actual = scheme.findColour('.', 2, null, null, 0);
+    assertEquals(actual, Color.WHITE);
+
+    /*
+     * 'L' in column 3, node 4, match emission 1.98342
+     * e-1.98342 = 0.1376 
+     * background frequency is 0.05
+     * ratio is 2.752, log is 1.012
+     * colour is graduated 1.012/2.996 or 86/255 of the way from
+     * white(255, 255, 255) to blue(0, 0, 255)
+     */
+    actual = scheme.findColour('L', 3, null, null, 0);
+    assertEquals(actual, new Color(169, 169, 255));
+
+    /*
+     * invalid symbol is White
+     */
+    actual = scheme.findColour('X', 2, null, null, 0);
+    assertEquals(actual, Color.WHITE);
+  }
+
+}
index fa4b5d9..c2f86d6 100644 (file)
@@ -4,9 +4,9 @@ import static org.testng.Assert.assertEquals;
 
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
-import jalview.gui.AlignViewport;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
+import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.Color;
 
@@ -83,7 +83,7 @@ public class PIDColourSchemeTest
      */
     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqs,
             DataSourceType.PASTE);
-    AlignViewport viewport = af.getViewport();
+    AlignmentViewport viewport = af.getViewport();
     viewport.setIgnoreGapsConsensus(false, af.alignPanel);
     while (viewport.getConsensusSeq() == null)
     {
diff --git a/test/jalview/util/Binned.csv b/test/jalview/util/Binned.csv
new file mode 100644 (file)
index 0000000..f140646
--- /dev/null
@@ -0,0 +1,4 @@
+1.8, 4.53
+3.4, 2.65
+0, 5.4
+6.4, 10.8
\ No newline at end of file
diff --git a/test/jalview/util/HMMProbabilityDistributionAnalyserTest.java b/test/jalview/util/HMMProbabilityDistributionAnalyserTest.java
new file mode 100644 (file)
index 0000000..4dbf05e
--- /dev/null
@@ -0,0 +1,119 @@
+package jalview.util;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import jalview.datamodel.HMMNode;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.testng.annotations.Test;
+
+import junit.extensions.PA;
+
+public class HMMProbabilityDistributionAnalyserTest {
+
+  HMMProbabilityDistributionAnalyser analyser = new HMMProbabilityDistributionAnalyser();
+
+  @Test
+  public void testMoveToFile() throws IOException
+  {
+
+    BufferedReader br = new BufferedReader(new FileReader(
+            "test/jalview/util/test_Fams_for_probability_analysis"));
+    analyser.moveLocationBy(1, br);
+
+    String line = br.readLine();
+    assertEquals(line, "# STOCKHOLM 1.0");
+    line = br.readLine();
+    assertEquals(line, "seq1 ATW");
+    line = br.readLine();
+    assertEquals(line, "seq2 ATI");
+
+  }
+
+  @Test
+  public void testCountValidResidues()
+  {
+    analyser.sequences = new Vector<>();
+    analyser.hmm = new HiddenMarkovModel();
+    analyser.hmm.setProperty("LENG", "8");
+
+    List<HMMNode> nodes = new ArrayList<>();
+    nodes.add(new HMMNode());
+    for (int i = 1; i < 9; i++)
+    {
+      HMMNode node = new HMMNode();
+      node.setResidueNumber(i - 1);
+      nodes.add(node);
+
+    }
+    PA.setValue(analyser.hmm, "nodes", nodes);
+
+    SequenceI[] sequence = new Sequence[] {
+        new Sequence("seq1", "ATGWWSCF"), new Sequence("seq2", "GGMKI"),
+        new Sequence("seq3", "--.ATccGc") };
+    analyser.sequences.add(sequence[0]);
+    analyser.sequences.add(sequence[1]);
+    analyser.sequences.add(sequence[2]);
+
+    int count = analyser.countValidResidues();
+    assertEquals(count, 16);
+  }
+
+  @Test(priority = 0)
+  public void testReadBinned() throws IOException
+  {
+    analyser.readBinned("test/jalview/util/");
+    Map<String, Double> map = analyser.binned;
+    assertEquals(map.get("1.8"), 4.53);
+    assertEquals(map.get("3.4"), 2.65);
+    assertEquals(map.get("6.4"), 10.8);
+    assertEquals(map.get("0"), 5.4);
+  }
+
+  @Test
+  public void testReadRaw() throws IOException
+  {
+    analyser.readRaw("test/jalview/util/");
+    List<ArrayList<Double>> list = analyser.raw;
+
+    assertEquals(list.get(0).get(0), 1.43);
+    assertNull(list.get(0).get(2));
+    assertEquals(list.get(1).get(1), 1.2);
+    assertEquals(list.get(2).get(0), 5.6);
+    assertEquals(list.get(2).get(2), 6.8);
+
+  }
+
+  @Test(priority = 1)
+  public void testProcessData() throws IOException
+  {
+    analyser.keepRaw = true;
+    BufferedReader brFam = new BufferedReader(new FileReader(
+            "test/jalview/util/test_Fams_for_probability_analysis"));
+    BufferedReader brHMM = new BufferedReader(new FileReader(
+            "test/jalview/util/test_HMMs_for_probability_analysis"));
+    analyser.readStockholm(brFam);
+    analyser.readHMM(brHMM);
+    analyser.processData(6);
+    Map<String, Double> map = analyser.binned;
+    List<ArrayList<Double>> list = analyser.raw;
+    assertEquals(map.get("1.8"), 4.863, 0.001d);
+    assertEquals(map.get("3.4"), 2.65);
+    assertEquals(map.get("0"), 5.4);
+    assertEquals(map.get("6.4"), 10.8);
+    assertEquals(map.get("1.4"), 0.166667, 0.00001d);
+    assertEquals(map.get("4.4"), 0.5);
+
+  }
+}
index 1acc9e1..cd3e124 100644 (file)
@@ -601,60 +601,6 @@ public class MapListTest
     assertEquals("[ [11, 16] ] 1:3 to [ [72, 53] ]", ml.toString());
   }
 
-  @Test(groups = "Functional")
-  public void testAddRange()
-  {
-    int[] range = { 1, 5 };
-    List<int[]> ranges = new ArrayList<>();
-
-    // add to empty list:
-    MapList.addRange(range, ranges);
-    assertEquals(1, ranges.size());
-    assertSame(range, ranges.get(0));
-
-    // extend contiguous (same position):
-    MapList.addRange(new int[] { 5, 10 }, ranges);
-    assertEquals(1, ranges.size());
-    assertEquals(1, ranges.get(0)[0]);
-    assertEquals(10, ranges.get(0)[1]);
-
-    // extend contiguous (next position):
-    MapList.addRange(new int[] { 11, 15 }, ranges);
-    assertEquals(1, ranges.size());
-    assertEquals(1, ranges.get(0)[0]);
-    assertEquals(15, ranges.get(0)[1]);
-
-    // change direction: range is not merged:
-    MapList.addRange(new int[] { 16, 10 }, ranges);
-    assertEquals(2, ranges.size());
-    assertEquals(16, ranges.get(1)[0]);
-    assertEquals(10, ranges.get(1)[1]);
-
-    // extend reverse contiguous (same position):
-    MapList.addRange(new int[] { 10, 8 }, ranges);
-    assertEquals(2, ranges.size());
-    assertEquals(16, ranges.get(1)[0]);
-    assertEquals(8, ranges.get(1)[1]);
-
-    // extend reverse contiguous (next position):
-    MapList.addRange(new int[] { 7, 6 }, ranges);
-    assertEquals(2, ranges.size());
-    assertEquals(16, ranges.get(1)[0]);
-    assertEquals(6, ranges.get(1)[1]);
-
-    // change direction: range is not merged:
-    MapList.addRange(new int[] { 6, 9 }, ranges);
-    assertEquals(3, ranges.size());
-    assertEquals(6, ranges.get(2)[0]);
-    assertEquals(9, ranges.get(2)[1]);
-
-    // not contiguous: not merged
-    MapList.addRange(new int[] { 11, 12 }, ranges);
-    assertEquals(4, ranges.size());
-    assertEquals(11, ranges.get(3)[0]);
-    assertEquals(12, ranges.get(3)[1]);
-  }
-
   /**
    * Check state after construction
    */
index 097ccd4..af82ac6 100644 (file)
@@ -1284,4 +1284,58 @@ public class MappingUtilsTest
     assertEquals(1, ranges.size());
     assertEquals(9, ranges.get(0)[1]);
   }
+
+  @Test(groups = "Functional")
+  public void testAddRange()
+  {
+    int[] range = { 1, 5 };
+    List<int[]> ranges = new ArrayList<>();
+  
+    // add to empty list:
+    MappingUtils.addRange(range, ranges);
+    assertEquals(1, ranges.size());
+    assertSame(range, ranges.get(0));
+  
+    // extend contiguous (same position):
+    MappingUtils.addRange(new int[] { 5, 10 }, ranges);
+    assertEquals(1, ranges.size());
+    assertEquals(1, ranges.get(0)[0]);
+    assertEquals(10, ranges.get(0)[1]);
+  
+    // extend contiguous (next position):
+    MappingUtils.addRange(new int[] { 11, 15 }, ranges);
+    assertEquals(1, ranges.size());
+    assertEquals(1, ranges.get(0)[0]);
+    assertEquals(15, ranges.get(0)[1]);
+  
+    // change direction: range is not merged:
+    MappingUtils.addRange(new int[] { 16, 10 }, ranges);
+    assertEquals(2, ranges.size());
+    assertEquals(16, ranges.get(1)[0]);
+    assertEquals(10, ranges.get(1)[1]);
+  
+    // extend reverse contiguous (same position):
+    MappingUtils.addRange(new int[] { 10, 8 }, ranges);
+    assertEquals(2, ranges.size());
+    assertEquals(16, ranges.get(1)[0]);
+    assertEquals(8, ranges.get(1)[1]);
+  
+    // extend reverse contiguous (next position):
+    MappingUtils.addRange(new int[] { 7, 6 }, ranges);
+    assertEquals(2, ranges.size());
+    assertEquals(16, ranges.get(1)[0]);
+    assertEquals(6, ranges.get(1)[1]);
+  
+    // change direction: range is not merged:
+    MappingUtils.addRange(new int[] { 6, 9 }, ranges);
+    assertEquals(3, ranges.size());
+    assertEquals(6, ranges.get(2)[0]);
+    assertEquals(9, ranges.get(2)[1]);
+  
+    // not contiguous: not merged
+    MappingUtils.addRange(new int[] { 11, 12 }, ranges);
+    assertEquals(4, ranges.size());
+    assertEquals(11, ranges.get(3)[0]);
+    assertEquals(12, ranges.get(3)[1]);
+  }
 }
diff --git a/test/jalview/util/Raw.csv b/test/jalview/util/Raw.csv
new file mode 100644 (file)
index 0000000..83d3452
--- /dev/null
@@ -0,0 +1,4 @@
+Seq1, Seq2, Seq3
+1.43, 2.34, 5.6,
+EMPTY, 1.2, 0.05,
+EMPTY, 5.4, 6.8,
\ No newline at end of file
diff --git a/test/jalview/util/test_Fams_for_probability_analysis b/test/jalview/util/test_Fams_for_probability_analysis
new file mode 100644 (file)
index 0000000..74fbab0
--- /dev/null
@@ -0,0 +1,13 @@
+# STOCKHOLM 1.0
+seq1 AW
+seq2 GW
+seq3 AW
+//
+# STOCKHOLM 1.0
+seq1 ATW
+seq2 ATI
+//
+# STOCKHOLM 1.0
+seq1 R-WW
+seq2 RAWW
+//
\ No newline at end of file
diff --git a/test/jalview/util/test_hmms_for_probability_analysis b/test/jalview/util/test_hmms_for_probability_analysis
new file mode 100644 (file)
index 0000000..b70d42b
--- /dev/null
@@ -0,0 +1,99 @@
+HMMER3/f [3.1b2 | February 2015]
+NAME  test1
+LENG  4
+ALPH  amino
+RF    no
+MM    no
+CONS  yes
+CS    no
+MAP   yes
+DATE  Fri Jul 21 06:35:06 2017
+NSEQ  3
+EFFN  3.000000
+CKSUM 657102310
+STATS LOCAL MSV       -5.0223  0.82341
+STATS LOCAL VITERBI   -4.9569  0.82341
+STATS LOCAL FORWARD   -2.0282  0.82341
+HMM          A        C        D        E        F        G        H        I        K        L        M        N        P        Q        R        S        T        V        W        Y   
+            m->m     m->i     m->d     i->m     i->i     d->m     d->d
+  COMPO   1.94296  5.20658  4.78882  4.52987  4.66525  2.54188  5.19553  2.25221  4.08549  3.87133  5.00250  4.55734  4.73106  4.65220  2.77287  3.67799  1.53923  3.75384  1.48526  4.84023
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01083  4.92694  5.64929  0.61958  0.77255  0.00000        *
+      1   0.67027  4.79120  4.60974  4.51892  5.43734  1.28080  5.43621  4.90028  4.64310  4.61059  5.39837  4.28688  4.41468  4.80804  4.79047  3.08135  3.44468  4.10506  6.74908  5.67939      1 A - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01083  4.92694  5.64929  0.61958  0.77255  0.48576  0.95510
+      2   5.43405  6.34487  5.85697  5.84679  4.39288  5.10370  5.65594  5.70664  5.69821  4.87848  6.25251  5.89664  5.70261  6.00722  5.60902  5.64576  5.80049  5.59366  0.08910  4.36301      2 W - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01083  4.92694  5.64929  0.61958  0.77255  0.48576  0.95510
+      3   3.42384  5.23617  4.84601  4.77568  5.39247  4.01365  5.64153  4.72950  4.75585  4.52264  5.55782  4.69647  4.81267  5.08969  4.87301  3.64217  0.20934  4.25217  6.65833  5.63018      3 T - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01083  4.92694  5.64929  0.61958  0.77255  0.48576  0.95510
+      4   3.53954  5.09963  4.71395  4.06038  4.20429  4.44020  4.65482  0.90152  3.16536  2.96072  4.13056  4.31689  4.83725  3.95143  1.46549  3.86829  3.78084  2.85654  5.74911  4.54685      4 i - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00730  4.92341        *  0.61958  0.77255  0.00000        *
+//
+HMMER3/f [3.1b2 | February 2015]
+NAME  test2
+LENG  3
+ALPH  amino
+RF    no
+MM    no
+CONS  yes
+CS    no
+MAP   yes
+DATE  Fri Jul 21 06:36:50 2017
+NSEQ  2
+EFFN  2.000000
+CKSUM 777554360
+STATS LOCAL MSV       -5.2452  0.95763
+STATS LOCAL VITERBI   -5.2886  0.95763
+STATS LOCAL FORWARD   -1.5134  0.95763
+HMM          A        C        D        E        F        G        H        I        K        L        M        N        P        Q        R        S        T        V        W        Y   
+            m->m     m->i     m->d     i->m     i->i     d->m     d->d
+  COMPO   1.33364  4.79082  4.44132  4.24796  3.91456  3.75718  4.85762  2.23342  4.16821  3.09137  4.29744  4.25088  4.41741  4.46803  4.31080  3.33397  1.39376  3.21010  2.54819  4.14914
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01467  4.62483  5.34718  0.61958  0.77255  0.00000        *
+      1   0.32372  4.76536  4.42980  4.32857  5.00499  3.55951  5.22620  4.27004  4.37081  4.10495  5.08789  4.22499  4.36948  4.63911  4.51684  3.12947  3.46009  3.76842  6.33337  5.25783      1 A - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01467  4.62483  5.34718  0.61958  0.77255  0.48576  0.95510
+      2   3.04414  4.87155  4.35068  4.21532  4.89213  3.66881  5.13994  4.14202  4.17893  3.96810  5.00600  4.23490  4.44590  4.53729  4.35178  3.25814  0.35496  3.73038  6.23308  5.12388      2 T - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01467  4.62483  5.34718  0.61958  0.77255  0.48576  0.95510
+      3   3.41901  4.77187  4.98694  4.49106  3.10447  4.49364  4.52024  1.21391  4.22709  2.30875  3.57865  4.53952  4.83367  4.43564  4.31127  3.88439  3.66452  2.61326  1.44329  3.34125      3 i - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  4.62006        *  0.61958  0.77255  0.00000        *
+//
+HMMER3/f [3.1b2 | February 2015]
+NAME  test3
+LENG  4
+ALPH  amino
+RF    no
+MM    no
+CONS  yes
+CS    no
+MAP   yes
+DATE  Fri Jul 21 06:37:01 2017
+NSEQ  2
+EFFN  2.000000
+CKSUM 986955970
+STATS LOCAL MSV       -5.4578  0.80004
+STATS LOCAL VITERBI   -5.2499  0.80004
+STATS LOCAL FORWARD   -2.1856  0.80004
+HMM          A        C        D        E        F        G        H        I        K        L        M        N        P        Q        R        S        T        V        W        Y   
+            m->m     m->i     m->d     i->m     i->i     d->m     d->d
+  COMPO   2.16700  5.33023  4.57707  4.32329  4.15728  4.03215  4.83242  4.49728  3.73978  4.00181  5.18156  4.45520  4.63709  4.41734  1.53081  3.84281  4.10073  4.20172  0.82417  4.15750
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01467  4.62483  5.34718  0.61958  0.77255  0.00000        *
+      1   4.09153  5.75008  4.67229  4.09411  5.31638  4.34678  4.67762  4.97541  2.93879  4.35023  5.37643  4.37234  4.85576  3.90366  0.27042  4.17197  4.33362  4.67489  6.11461  5.14175      1 R - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.39762  4.62483  1.14482  0.61958  0.77255  0.48576  0.95510
+      2   0.58385  4.42717  3.89187  3.72118  4.47383  3.23815  4.69159  3.65968  3.74862  3.52210  4.52478  3.76053  4.01438  4.05655  3.96007  2.78076  3.08518  3.24526  5.86063  4.71068      2 A - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.02145  4.24866  4.97100  0.61958  0.77255  0.27360  1.42978
+      3   4.82318  5.87391  5.36844  5.28961  3.81117  4.70308  5.10523  4.98084  5.06729  4.21822  5.56037  5.33222  5.28501  5.40387  5.04111  5.02415  5.17266  4.88017  0.16601  3.78547      3 W - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01467  4.62483  5.34718  0.61958  0.77255  0.48576  0.95510
+      4   4.82318  5.87391  5.36844  5.28961  3.81117  4.70308  5.10523  4.98084  5.06729  4.21822  5.56037  5.33222  5.28501  5.40387  5.04111  5.02415  5.17266  4.88017  0.16601  3.78547      4 W - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.00990  4.62006        *  0.61958  0.77255  0.00000        *
+//
\ No newline at end of file
index 80b48c3..134fbd1 100644 (file)
@@ -28,6 +28,7 @@ import jalview.ws.jabaws.JalviewJabawsTestUtils;
 import jalview.ws.jws2.JabaPreset;
 import jalview.ws.jws2.Jws2Discoverer;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ParamDatastoreI;
 
 import java.awt.BorderLayout;
 import java.awt.event.WindowAdapter;
@@ -42,6 +43,7 @@ import javax.swing.JPanel;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import compbio.metadata.Argument;
 import compbio.metadata.Preset;
 import compbio.metadata.PresetManager;
 
@@ -58,12 +60,12 @@ public class Jws2ParamView
   /**
    * which services to test
    */
-  public static List<String> serviceTests = new ArrayList<String>();
+  public static List<String> serviceTests = new ArrayList<>();
 
   /**
    * which presets to test for services
    */
-  public static List<String> presetTests = new ArrayList<String>();
+  public static List<String> presetTests = new ArrayList<>();
   static
   {
     serviceTests.add("AAConWS".toLowerCase());
@@ -127,11 +129,12 @@ public class Jws2ParamView
             }
             pr = en.next();
           }
-          WsJobParameters pgui = new WsJobParameters(service,
-                  new JabaPreset(service, pr));
-          JFrame jf = new JFrame(MessageManager.formatMessage(
-                  "label.ws_parameters_for",
-                  new String[] { service.getActionText() }));
+          WsJobParameters pgui = new WsJobParameters((ParamDatastoreI) null,
+                  service, new JabaPreset(service, pr),
+                  (List<Argument>) null);
+          JFrame jf = new JFrame(MessageManager
+                  .formatMessage("label.ws_parameters_for", new String[]
+                  { service.getActionText() }));
           jf.setSize(700, 800);
           JPanel cont = new JPanel(new BorderLayout());
           pgui.validate();
index 01973d2..ab53613 100755 (executable)
@@ -36,7 +36,7 @@
                <param name="file2" value="${file2}" />
        </antcall>
        <echo message=" "/>
-       <echo message="Missing message labels in Messages.properties compare to ${file2}"/>
+       <echo message="Missing message labels in Messages.properties compared to ${file2}"/>
        <antcall target="compareProperties">
                <param name="file2" value="resources/lang/Messages.properties"/>
                <param name="file1" value="${file2}" />