Merge branch 'alpha/JAL-3362_Jalview_212_alpha' into merge-212
authorJim Procter <jprocter@issues.jalview.org>
Tue, 13 Aug 2019 15:22:01 +0000 (16:22 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Tue, 13 Aug 2019 15:22:01 +0000 (16:22 +0100)
231 files changed:
doc/addingWebClient.md [new file with mode: 0644]
examples/groovy/hmmertestimport.groovy [new file with mode: 0644]
examples/testdata/hmmer3/alignment_frag.fa.gz [new file with mode: 0644]
examples/testdata/hmmer3/alignment_res.fa.gz [new file with mode: 0644]
examples/testdata/hmmer3/hit_fragment.json.gz [new file with mode: 0644]
examples/testdata/hmmer3/hmmeresult.json.gz [new file with mode: 0644]
examples/uniref50.hmm [new file with mode: 0644]
help/help/help.jhm
help/help/helpTOC.xml
help/help/html/features/preferences.html
help/help/html/menus/alwhmmer.html [new file with mode: 0644]
resources/ProbabilityOfMatch [new file with mode: 0644]
resources/lang/Messages.properties
resources/lang/Messages_es.properties
schemas/jalview.xsd
src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java
src/jalview/analysis/AAFrequency.java
src/jalview/analysis/AlignmentSorter.java
src/jalview/analysis/AlignmentUtils.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/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/AlignmentView.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/Desktop.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/RestServiceEditorPane.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/hmmer/JackHMMER.java [new file with mode: 0644]
src/jalview/hmmer/Search.java [new file with mode: 0644]
src/jalview/io/AlignFile.java
src/jalview/io/CountReader.java [new file with mode: 0644]
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/SequenceAnnotationReport.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/project/Jalview2XML.java
src/jalview/renderer/AnnotationRenderer.java
src/jalview/renderer/ResidueShaderI.java
src/jalview/schemes/AnnotationColourGradient.java
src/jalview/schemes/HMMMatchScoreColourScheme.java [new file with mode: 0644]
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/Comparison.java
src/jalview/util/FileUtils.java [new file with mode: 0644]
src/jalview/util/HMMProbabilityDistributionAnalyser.java [new file with mode: 0644]
src/jalview/util/HttpUtils.java
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/util/StringUtils.java
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/AWsJob.java
src/jalview/ws/WSClient.java
src/jalview/ws/api/CancellableI.java [new file with mode: 0644]
src/jalview/ws/api/DistanceMatrixResultI.java [new file with mode: 0644]
src/jalview/ws/api/JalviewServiceEndpointProviderI.java [new file with mode: 0644]
src/jalview/ws/api/JalviewWebServiceI.java [new file with mode: 0644]
src/jalview/ws/api/JobId.java [new file with mode: 0644]
src/jalview/ws/api/MsaI.java [new file with mode: 0644]
src/jalview/ws/api/MsaResultI.java [new file with mode: 0644]
src/jalview/ws/api/MsaWithGuideTreeI.java [new file with mode: 0644]
src/jalview/ws/api/MultipleSequenceAlignmentI.java [new file with mode: 0644]
src/jalview/ws/api/ServiceWithParameters.java [new file with mode: 0644]
src/jalview/ws/api/TreeResultI.java [new file with mode: 0644]
src/jalview/ws/api/UIinfo.java [new file with mode: 0644]
src/jalview/ws/ebi/HmmerJSONProcessor.java [new file with mode: 0644]
src/jalview/ws/ebi/hmmerClient.java [new file with mode: 0644]
src/jalview/ws/gui/MsaWSJob.java [new file with mode: 0644]
src/jalview/ws/gui/MsaWSThread.java [moved from src/jalview/ws/jws2/MsaWSThread.java with 52% similarity]
src/jalview/ws/gui/WsJob.java [new file with mode: 0644]
src/jalview/ws/jws1/MsaWSClient.java
src/jalview/ws/jws1/MsaWSThread.java
src/jalview/ws/jws1/SeqSearchWSClient.java
src/jalview/ws/jws1/SeqSearchWSThread.java
src/jalview/ws/jws2/AAConClient.java
src/jalview/ws/jws2/AADisorderClient.java
src/jalview/ws/jws2/AbstractJabaCalcWorker.java
src/jalview/ws/jws2/JabaParamStore.java
src/jalview/ws/jws2/JabaPreset.java
src/jalview/ws/jws2/JabaWsParamTest.java [new file with mode: 0644]
src/jalview/ws/jws2/JabawsCalcWorker.java
src/jalview/ws/jws2/JabawsMsaInterfaceAlignCalcWorker.java
src/jalview/ws/jws2/Jws2Client.java
src/jalview/ws/jws2/Jws2Discoverer.java
src/jalview/ws/jws2/MsaWSClient.java
src/jalview/ws/jws2/RNAalifoldClient.java
src/jalview/ws/jws2/SequenceAnnotationWSClient.java
src/jalview/ws/jws2/dm/AAConSettings.java
src/jalview/ws/jws2/dm/JabaOption.java
src/jalview/ws/jws2/jabaws2/JabawsMsaInstance.java [new file with mode: 0644]
src/jalview/ws/jws2/jabaws2/Jws2Instance.java
src/jalview/ws/params/OptionI.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/FileParameter.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/RadioChoiceParameter.java [moved from src/jalview/ws/params/simple/StringChoiceParameter.java with 65% similarity]
src/jalview/ws/params/simple/StringParameter.java [new file with mode: 0644]
src/jalview/ws/rest/InputType.java
src/jalview/ws/rest/RestClient.java
src/jalview/ws/rest/RestJobThread.java
src/jalview/ws/rest/RestServiceDescription.java
src/jalview/ws/rest/clientdefs/ShmrRestClient.java [new file with mode: 0644]
src/jalview/xml/binding/jalview/AlcodonFrame.java
src/jalview/xml/binding/jalview/Annotation.java
src/jalview/xml/binding/jalview/AnnotationColourScheme.java
src/jalview/xml/binding/jalview/AnnotationElement.java
src/jalview/xml/binding/jalview/DoubleMatrix.java
src/jalview/xml/binding/jalview/DoubleVector.java
src/jalview/xml/binding/jalview/Feature.java
src/jalview/xml/binding/jalview/FeatureMatcher.java
src/jalview/xml/binding/jalview/FeatureMatcherSet.java
src/jalview/xml/binding/jalview/FilterBy.java
src/jalview/xml/binding/jalview/JalviewModel.java
src/jalview/xml/binding/jalview/JalviewUserColours.java
src/jalview/xml/binding/jalview/MapListType.java
src/jalview/xml/binding/jalview/Mapping.java
src/jalview/xml/binding/jalview/NoValueColour.java
src/jalview/xml/binding/jalview/ObjectFactory.java
src/jalview/xml/binding/jalview/PcaDataType.java
src/jalview/xml/binding/jalview/Pdbentry.java
src/jalview/xml/binding/jalview/Sequence.java
src/jalview/xml/binding/jalview/SequenceSet.java
src/jalview/xml/binding/jalview/SequenceType.java
src/jalview/xml/binding/jalview/ThresholdType.java
src/jalview/xml/binding/jalview/VAMSAS.java
src/jalview/xml/binding/jalview/WebServiceParameterSet.java
src/jalview/xml/binding/jalview/package-info.java
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/PopupMenuTest.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/FileLoaderTest.java
test/jalview/io/FormatAdapterTest.java
test/jalview/io/HMMAlignmentTest.sto [new file with mode: 0644]
test/jalview/io/HMMAlignmentTestHMM.hmm [new file with mode: 0644]
test/jalview/io/HMMFileTest.java [new file with mode: 0644]
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/project/Jalview2xmlTests.java
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/FileUtilsTest.java [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/StringUtilsTest.java
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/ebi/HmmerJSONProcessTest.java [new file with mode: 0644]
test/jalview/ws/gui/Jws2ParamView.java
test/jalview/ws/jabaws/DisorderAnnotExportImport.java
test/jalview/ws/jabaws/RNAStructExportImport.java
test/jalview/ws/jws2/ParameterUtilsTest.java
test/jalview/ws/rest/ShmmrRSBSService.java
utils/i18nAnt.xml

diff --git a/doc/addingWebClient.md b/doc/addingWebClient.md
new file mode 100644 (file)
index 0000000..0d0ee1d
--- /dev/null
@@ -0,0 +1,68 @@
+# How to add a web service backend to Jalview's web services UI
+
+### Document Status: *Work in progress !*
+
+There are two phases to services.
+
+ *Discovery* threads are started by jalview.gui.Desktop (or other UI components or the CLI if they are headless services accessible via commandline). Your service discovery thread registers discovered instances so they can be accessed by the user.
+
+ *Access* most services are accessed by selecting a menu item, option, or specifying a nickname for the service instance as a Jalview command line parameter. Different access patterns are used for the various services: seqeunce data source, sequence feature annotation source, multiple sequence alignment, multiple alignment annotation source, etc. There should be no need for your code to create UI components (if there is then Jalview's UI needs to be refactored to avoid this).
+
+## Discovery
+
+*jalview.gui.Desktop*
+- start a discovery thread to discover services provided by your framework. The discoverer should generate a list of objects that either implement WsMenuEntryProviderI or provide another mechanism to add themselves to Jalview's menus (via jalview.gui.AlignFrame.BuildWebServiceMenu() below)
+
+*jalview.gui.AlignFrame*
+- BuildWebServiceMenu()
+ This method creates a runnable that's called when the available set of web services changes (e.g. when a discovery thread completes). Add code to the Runnable's run method to create Menu Items in the web services menu via jalview.ws.WSMenuEntryProviderI instances generated by your discoverer. 
+
+
+## Types of service
+
+### Services that create new alignments or windows, optionally with a progress log
+
+The pattern for these services requires a Client that initates a thread which creates, and montors one or more jobs based on input data.
+
+jalview.ws.MsaWSClient -- currently does double duty with Jaba services for alignment analysis and instantiation of alignment services.
+
+jalview.ws.gui.MSAThread -- UI model and controller for a running MSA service. Instantiated with an instance of jalview.ws.MultipleSequenceAlignmentI provided by the service endpoint factory.
+
+
+## Other classes of interest
+
+### jalview.ws.api
+
+Interfaces and base classes to be implemented and used by a service endpoint.
+
+ jalview.ws.api.CancellableI.java - implement if the service is cancellable
+ jalview.ws.api.JalviewWebServiceI.java - base service interface
+ jalview.ws.api.JobId.java - a timestamped job id that can be saved in a Jalview project
+
+#### submission interfaces
+jalview.ws.api.MsaI.java
+jalview.ws.api.MsaWithGuideTreeI.java
+
+
+#### result interfaces
+jalview.ws.api.MsaResultI.java
+jalview.ws.api.TreeResultI.java
+jalview.ws.api.DistanceMatrixResultI.java
+
+
+#### minimal composed interfaces for a complete functional analysis 
+
+jalview.ws.api.MultipleSequenceAlignmentI.java
+
+
+#### base class for a service endpoint instance - to be materialised by service discoverers
+
+jalview.ws.api.UIinfo.java - basic information 
+jalview.ws.api.ServiceWithParameters.java
+
+jalview.ws.api.JalviewServiceEndpointProviderI - implemented by service endpoint factories (typically extended from UIinfo or ServiceWithParameters).
+
+
+## Analysis services
+
+These have not yet been refactored. Feel free to look at how jalview.ws.jws2.AACons and Disorder clients operate and adapt the pattern for your own services. The Groovy example in the help [[help/html/groovy/featuresCounter.html]] for creating custom annotation tracks uses the same basic 'alignment analysis worker' mechanism to provide dynamically executed alignment analysis calculations that result in annotation tracks displayed below the alginment.
diff --git a/examples/groovy/hmmertestimport.groovy b/examples/groovy/hmmertestimport.groovy
new file mode 100644 (file)
index 0000000..88bd0e1
--- /dev/null
@@ -0,0 +1,6 @@
+// def alv = new jalview.io.FileLoader().LoadFileWaitTillLoaded("examples/testdata/hmmer3/alignment_res.fa.gz","File").getViewport();
+def alv = jalview.bin.Jalview.getCurrentAlignFrame().getViewport();
+def al = alv.getAlignment();
+def jproc = new jalview.ws.ebi.HmmerJSONProcessor(al)
+jproc.parseFrom(new jalview.io.FileParse("/Users/jprocter/git/jalview/examples/testdata/hmmer3/hmmeresult.json.gz",jalview.io.DataSourceType.FILE))
+jproc.updateView(alv)
\ No newline at end of file
diff --git a/examples/testdata/hmmer3/alignment_frag.fa.gz b/examples/testdata/hmmer3/alignment_frag.fa.gz
new file mode 100644 (file)
index 0000000..a4e79b2
Binary files /dev/null and b/examples/testdata/hmmer3/alignment_frag.fa.gz differ
diff --git a/examples/testdata/hmmer3/alignment_res.fa.gz b/examples/testdata/hmmer3/alignment_res.fa.gz
new file mode 100644 (file)
index 0000000..03206f4
Binary files /dev/null and b/examples/testdata/hmmer3/alignment_res.fa.gz differ
diff --git a/examples/testdata/hmmer3/hit_fragment.json.gz b/examples/testdata/hmmer3/hit_fragment.json.gz
new file mode 100644 (file)
index 0000000..bbc8405
Binary files /dev/null and b/examples/testdata/hmmer3/hit_fragment.json.gz differ
diff --git a/examples/testdata/hmmer3/hmmeresult.json.gz b/examples/testdata/hmmer3/hmmeresult.json.gz
new file mode 100644 (file)
index 0000000..c3fa9a2
Binary files /dev/null and b/examples/testdata/hmmer3/hmmeresult.json.gz differ
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 47f7d53..dabfd17 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 7e358d6..1f15e45 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 5fda2df..41dae1d 100755 (executable)
@@ -64,6 +64,9 @@
     <li>The <a href="#editing"><strong>&quot;Editing&quot;</strong>
         Preferences</a> tab contains settings affecting behaviour when editing alignments.
     </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="../webServices/webServicesPrefs.html"><strong>&quot;Web
           Service&quot;</strong> Preferences</a> tab allows you to configure the <a
       href="http://www.compbio.dundee.ac.uk/jabaws">JABAWS</a>
     <em>Sort with New Tree</em> - When selected, any trees calculated or
     loaded onto the alignment will automatically sort the alignment.
   </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>
   <p>&nbsp;</p>
   <em>Web Services Preferences</em> - documentation for this tab is
   given in the
diff --git a/help/help/html/menus/alwhmmer.html b/help/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>
diff --git a/resources/ProbabilityOfMatch b/resources/ProbabilityOfMatch
new file mode 100644 (file)
index 0000000..9e3869f
--- /dev/null
@@ -0,0 +1,261 @@
+0.2
+A
+200, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2
+, 0.20369859505605942, 0.4222571919176904, 0.02232980369562049, 0.026676627662949624, 0.03525533903309387, 0.04787669271298644, 0.05605478196465866, 0.0641749787418314, 0.10286871806399077, 0.12105923035393054, 0.12422338883170829, 0.10304081214854802, 0.10333588151825282, 0.10114320874739426, 0.11812749552768892, 0.15006056120099137, 0.2237625777282616, 0.30253227447901293, 0.388557592836257, 0.43721427997253054, 0.47970928320880174, 0.5289808943443863, 0.5486523348637581, 0.5583247254358412, 0.5484761487937164, 0.5995060657240099, 0.6195991719342547, 0.6227297938639322, 0.6284738072714547, 0.5548992929945823, 0.5416658828311707, 0.5848669247143425, 0.5528051163252368, 0.6785332996776757, 0.5806004778403442, 0.18593167643573633, 0.38318927736500424
+400, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8
+, 0.00538163724710359, 0.050246851326647975, 0.00325623383324987, 0.016089404836314707, 0.004768961434464644, 0.012975554662909325, 0.014612779422905292, 0.036453046922170884, 0.03669851726847946, 0.06053063401623625, 0.07734802668205788, 0.14448615467437756, 0.24953322777140308, 0.34806276783515594, 0.4229567261622065, 0.4873077681738967, 0.5401722415436365, 0.5521510226102508, 0.6000517399892216, 0.6107765515229574, 0.5870927019689605, 0.6298630970573851, 0.6879023365675971, 0.6221611553796009, 0.632263810408655, 0.689461445849211, 0.6390236708841557, 0.7242036199282817, 0.6557168681820945, 0.21069080034931634
+600, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.009258546378795182, 0.022829316518316413, 0.022698074547786367, 0.012736836086937675, 0.016469563173777596, 0.01913720324613999, 0.03173961484046805, 0.04293589176349238, 0.08585848446208531, 0.16926121837954017, 0.293436232527367, 0.3543603601267507, 0.48651755499862337, 0.5103148855367983, 0.5876985421521675, 0.5784255879120095, 0.5938007169568057, 0.5598080715719793, 0.691548146841681, 0.6943388099375437, 0.6996541955589088, 0.7434201980299975, 0.8365119642131629, 0.9095567810750043, 0.5207569176305396, 0.7405911308670332
+800, -2.4, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4
+, 0.008917934185414377, 0.01017895688795886, 0.037528784049424314, 0.02798827469166613, 0.03137703539242772, 0.11784556048768703, 0.11121306048524869, 0.20430912771074103, 0.2598593792958281, 0.4306348256035734, 0.46316119541365697, 0.5405314728294079, 0.539282096838667, 0.42055185929928385, 0.5448818087581953, 0.5997338164946914, 0.62308312092143, 0.7089840268242462, 0.6436353618329662, 0.826552573493094, 0.7908826508888537, 0.6905508284818629, 0.3823632872193804
+1000, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2
+, 0.006152180116633862, 0.015427371964555698, 0.02331992788794896, 0.10944473717642993, 0.19333261931256743, 0.2004513811627833, 0.2384363292885486, 0.5272892625055869, 0.5168199037063749, 0.5652991338441917, 0.4397653398451027, 0.46013409044401904, 0.5175981692561336, 0.6704643484850927, 0.7969708452261104, 0.4745152293484279, 0.9101407067992686, 0.9288992619408138, 0.8325611428419273
+10000000, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 2.0
+, 0.0013574547186773595, 0.07926513808931503, 0.07102964878743583, 0.0726328476783432, 0.188665578230727, 0.4670863411106134, 0.6080090637275772, 0.44379833749922704, 0.5310140600224029, 0.5931610388683948, 0.4655146952326047, 0.7948299079449878, 0.45438605875039634, 0.7676093316330358, 0.5325662206236474, 0.5570031538223215
+Q
+200, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.8
+, 0.030660402054098843, 0.029515962408728325, 0.01386298123421587, 0.03323790765774019, 0.050077081129415675, 0.029026658778299946, 0.04803400920855964, 0.046080800910896676, 0.05350762941049219, 0.07623076885791424, 0.07766677224262616, 0.12818678386245805, 0.13808429251771162, 0.15976782729500769, 0.18553311032498795, 0.21473885233239454, 0.26862488576858196, 0.3335898147114968, 0.3933292215057105, 0.4471255648270871, 0.5140106474150711, 0.5606446177282451, 0.56645579177951, 0.6187003826533546, 0.6264565231734968, 0.6902587142708823, 0.7310434998635741, 0.7404822151595194, 0.7455970773478046, 0.8194310136729327, 0.754028761152219, 0.6904665436774613, 0.7865490878301985, 0.8251017523682402, 0.25767625767590513, 0.09683794373033726
+400, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4
+, 0.015174619218570292, 0.037092256738479906, 0.02807957626685945, 0.020952215954002592, 0.012490724790011861, 0.015060526993713729, 0.02337051753316606, 0.03585907871833321, 0.04997995343607782, 0.05116995577905059, 0.08421567659761686, 0.11469062311930732, 0.1729106310315939, 0.19279889620933457, 0.2305248874399254, 0.26979519803194807, 0.35005713230775476, 0.442197230272885, 0.5123688583661171, 0.5530137422740864, 0.5569824269831563, 0.5644003448573167, 0.5847125012080069, 0.6854939519416933, 0.7023668672066997, 0.7154562402783202, 0.7676568753108612, 0.8390636087066714, 0.8073438244745248, 0.7137044911123218, 0.7005129526561815, 0.660501122004602, 0.977346670748799
+600, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2
+, 0.06409443044310832, 0.17043537478138396, 0.06708416589502411, 0.04885363429869391, 0.03348033250104629, 0.05051027800044158, 0.027081552065751212, 0.05641650262162609, 0.08745592321636787, 0.13269225526345627, 0.17856051100094275, 0.2604735522213605, 0.2257012643447686, 0.33727227847072533, 0.43694229465002715, 0.47575874028429543, 0.5515806648065332, 0.5766003713260374, 0.5333600150424079, 0.6251127815619932, 0.6323814616237637, 0.7636923593854934, 0.8150120235799707, 0.8554510812808985, 0.8528317416457601, 0.8932737202285638, 0.8996973853124699, 0.7504095750846632, 0.0782035688876777
+800, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.6, 2.8, 3.0, 3.2
+, 0.008569761190854706, 0.01818566336086026, 0.0035886737075778684, 0.019557202027668318, 0.04730700327264522, 0.11713253719294132, 0.11747711101000212, 0.13566131005576462, 0.22173593877845912, 0.23226589196469324, 0.3285201642634684, 0.40175918428239643, 0.514273714962315, 0.6426839325030723, 0.5592607511903168, 0.4484374500207914, 0.4271084024627013, 0.5761775665904221, 0.7207597567939774, 0.8261386365447307, 0.9533012758522402, 0.9546438827372017, 0.9144745505555422, 0.5300797598551829, 0.3222227681422887
+1000, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 3.0
+, 0.03406830709780076, 0.059250254494420895, 0.06295161152712787, 0.14778317919449488, 0.2052302207229962, 0.18103793431053206, 0.27419636115330304, 0.43791113182322405, 0.5014274959179482, 0.6332032204767004, 0.4625651540928214, 0.5822609669670592, 0.46439614255985395, 0.5769223811890896, 0.7117235531057876, 0.7830268783073607, 0.7662000487154872, 0.9574188255261584, 0.9791270764706063, 0.3459984609465178
+10000000, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.4
+, 0.011375782562223234, 0.015110412493978646, 0.025236652426745946, 0.08429389717841733, 0.14087146909054712, 0.11134410528964563, 0.7012573537893643, 0.6706932505976297, 0.36458107960413166, 0.4313977123835829, 0.5936455596283988, 0.6425632118499391, 0.5015729047474079, 0.692265646351462, 0.8633350923482849, 0.4146853327478658, 0.4854770135494893
+L
+200, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2
+, 0.022694200314865198, 0.04438120468049618, 0.2034621056438575, 0.09596674258314453, 0.0936871324670998, 0.14776469827002428, 0.13802184826675024, 0.13439766666587188, 0.04220458436568829, 0.16944536376489286, 0.11668704319818315, 0.10097026506035328, 0.13321742110406912, 0.1826244747204611, 0.24029848496689793, 0.27293725510554856, 0.3702265782860514, 0.39675970663839577, 0.3865827048643012, 0.4121574468469467, 0.42297029574231776, 0.42374694961798354, 0.45387310170747625, 0.4990958786276845, 0.5249310443913181, 0.5568838889388209, 0.5814034735034034, 0.5874918865708025, 0.544773016253518, 0.5740018578298114, 0.5921713379469711, 0.631807381420908, 0.7064114207808031, 0.7452793584039196, 0.5607075738856433, 0.6177654347620544, 0.2210712700377047, 0.0341445893559449
+400, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.022810154959402515, 0.022810154959402515, 0.007720793314408286, 0.020949129787512125, 0.008085477457937203, 0.025751402801163902, 0.010533333633145176, 0.019532582257393728, 0.02675455267790389, 0.04368701982880921, 0.0642728570843146, 0.09326829811586024, 0.1600825548451298, 0.2628755953431343, 0.33349628915200696, 0.3715599414484014, 0.39048003188172026, 0.3639567373219425, 0.3686159885628984, 0.3815167578493698, 0.4323222079737531, 0.47570929722908906, 0.5414607289365889, 0.5729269739868003, 0.6300711763621937, 0.6385473260853091, 0.6476475561759117, 0.6476414812252087, 0.6798341599008929, 0.7011957467766897, 0.6072402235385015, 0.6366008002469443, 0.28404340538354134
+600, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.004522531317523935, 0.005379331911902031, 0.041373584208902116, 0.06341550713400419, 0.00541136917154892, 0.024970967450366772, 0.01737419159452633, 0.02698710179147721, 0.10931342415377847, 0.16986739364325762, 0.3018235387326877, 0.3955846475210277, 0.36463488371059793, 0.35591519236678093, 0.33945447736638934, 0.3474316317416148, 0.40674510340538544, 0.45543036568909234, 0.5303127712434488, 0.5480395796161592, 0.6182397608837148, 0.6337199392749969, 0.6954318960326403, 0.7741570775389336, 0.7714912509580867, 0.8938303831713577, 0.8447712444019307, 0.6180977910562903, 0.09687554836070501
+800, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0
+, 0.00376740149279639, 0.008994324259810987, 0.011217681458643158, 0.01782829505291646, 0.06663319133607505, 0.10356871471685111, 0.22278722861655195, 0.42553503993613984, 0.36496033595587996, 0.3610925735058211, 0.3820858282736695, 0.4198207783566425, 0.4120354668294257, 0.41931435853443944, 0.3957678881854993, 0.530671191878201, 0.5316696899190078, 0.5311791062303839, 0.5776547205659004, 0.6069486624133318, 0.6843818658889624, 0.6689819508356897, 0.851214696227136
+1000, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8
+, 0.032368973346990515, 0.13969512844032048, 0.2276500581125476, 0.4431061395070267, 0.44559967376517107, 0.4080484956725524, 0.345312870981004, 0.5593329427588312, 0.3453546578106801, 0.39706278392354083, 0.4575762231727116, 0.5177464816296974, 0.47914956650885854, 0.5118580467178341, 0.6401841274969214, 0.6712200329105288, 0.6463117979877456, 0.42810448131912826
+10000000, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6
+, 0.01782272397306565, 0.09395030002738014, 0.28736733981389734, 0.4610503140581492, 0.4504825574929253, 0.5433177175779089, 0.39843618244538137, 0.35264792682742047, 0.2477238149909607, 0.36972491007649827, 0.4492191259986524, 0.4335075346288497, 0.5333388835840573, 0.5258079002931256, 0.4621631821269529, 0.6088093248295579, 0.7590881193363881, 0.7903597389905895
+S
+200, -4.2, -4.0, -3.8, -3.6, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.12438418712700766, 0.017446874253851875, 0.18519360573679758, 0.22124855285421674, 0.059752889119277716, 0.042504821227910966, 0.0663164525876336, 0.029121816870577095, 0.05492112929293922, 0.06720779941392006, 0.08127909407093194, 0.0560348871102672, 0.09659058156200162, 0.10353812840581252, 0.1210800822205396, 0.1562651703452635, 0.20319933061104634, 0.26245317523800094, 0.3369190441521257, 0.4095080052105503, 0.48191521218608413, 0.5284157963491289, 0.5606549634969592, 0.5950347464160363, 0.6187357500970652, 0.6470608094279561, 0.6356898770675693, 0.6714774329043008, 0.6121942241790169, 0.6095743971384333, 0.6564633462830982, 0.8280795031669954, 0.726251886423071, 0.7056292388804567, 0.6339622337745136
+400, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8
+, 0.03629666034518226, 0.010251346587675996, 0.00588376225845094, 0.017103038428544992, 0.014167000294475663, 0.027002831996804307, 0.022073022212184695, 0.03815019381933721, 0.056348100149132954, 0.08949481882232799, 0.11963538365342391, 0.17229156999292647, 0.23102140894642761, 0.30799404180594553, 0.39670138039825537, 0.4994930747566133, 0.5572615383451857, 0.5696161186424068, 0.6158152862031046, 0.6439833627431268, 0.6519249573567936, 0.6333835930691046, 0.6961475696922559, 0.6193005635430306, 0.6552521049455082, 0.7202828580642087, 0.7532262221700042, 0.8334731780932044, 0.2368772002791371
+600, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8
+, 0.013059399423161333, 0.24102871126123523, 0.01585339152122089, 0.028060159218492607, 0.026905462227703764, 0.04927252800462799, 0.03723841497717851, 0.02803294010626132, 0.03829902396434643, 0.06344601230608479, 0.057968769867864034, 0.10541929960012424, 0.19562626406778896, 0.27703475443325176, 0.41179023162123574, 0.5335069983729668, 0.5546150860338063, 0.5747348009876617, 0.5514881911764865, 0.6364965911968703, 0.6801059018570212, 0.6534703205286367, 0.5564196913416785, 0.7302176125008304, 0.8131069350450936, 0.8027519219958231, 0.6085485091562549, 0.8202839094617357, 0.405278218549064
+800, -2.4, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.04216693629487124, 0.0043830307084839195, 0.014462196442335668, 0.01919041673092326, 0.01977825622316669, 0.023712744831969675, 0.055443290493752295, 0.08851448392127609, 0.11455256546377275, 0.2328694553482898, 0.3367326328850246, 0.459317221407433, 0.5879316224828962, 0.6470056873737324, 0.570650862440862, 0.7095801714949331, 0.706462120036267, 0.7170494260774206, 0.6295006361454005, 0.7778910581389612, 0.7148705132619393, 0.7592112207571959, 0.7482104188792188, 0.9522502952396771
+1000, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0
+, 0.026214357205221576, 0.04427631406271417, 0.1264935961447764, 0.14077609356326534, 0.2960780435431137, 0.38160536439121107, 0.474947107253397, 0.5727918213213382, 0.6855543310528419, 0.6138913582635468, 0.5778692630210621, 0.6580943515434279, 0.6050444129262045, 0.6168509337333394, 0.8288146290440119, 0.6657847422198185
+10000000, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.2
+, 0.027142096860031932, 0.013757755597518209, 0.0227211975407645, 0.05284974093264248, 0.048659901118917506, 0.16142942336804442, 0.12657774238502886, 0.26692784650029305, 0.3779063407756724, 0.643762567432302, 0.49130042503233945, 0.7242627649143978, 0.6783062480117502, 0.6304716291654356, 0.7038812933324693, 0.9237125448626993, 0.620579612380977, 0.6038819322983577, 0.4726479391294941
+R
+200, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.03207726503553209, 0.005274482832016623, 0.02353481066931443, 0.01858536618468486, 0.029482970704681824, 0.029822145312603715, 0.03156800848371642, 0.030513654789762576, 0.04606365662704011, 0.04081943283545797, 0.05812095484759577, 0.07558217960358522, 0.08275712090661415, 0.09765221787115734, 0.13423340776679776, 0.1489303205649009, 0.2101302968591223, 0.241768086761866, 0.28003078459011693, 0.3620682642630574, 0.41228413694312804, 0.4842228134280171, 0.5208837054055414, 0.5601867659345883, 0.5971129002888642, 0.5931505256179169, 0.6398668937991495, 0.6522501064755667, 0.6681713881294856, 0.6631087700660413, 0.6581604871860909, 0.6224264678321053, 0.6767846770830652, 0.6536296591076727, 0.47393142233152774, 0.6996554390188527, 0.5687643264275022, 0.6981446635867379, 0.4736078327732734
+400, -3.4, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.06120237498398166, 0.041651302875030785, 0.005403336877600516, 0.005329713060580334, 0.014009522483041804, 0.030143197221196488, 0.030445491091082598, 0.029049177244755166, 0.04466300930040355, 0.02959186639672202, 0.07858217329768569, 0.10613250573098461, 0.13756433589801076, 0.1753766185741036, 0.24220992595864874, 0.3379268214752498, 0.43933847181192914, 0.4687608305155847, 0.5219843880663324, 0.5378031723967835, 0.5885073150547451, 0.5790215715229141, 0.6033105062790582, 0.6369385345570912, 0.6367438494487759, 0.6442980558476543, 0.7448119005362304, 0.6787320027676245, 0.7192587968629324, 0.6923730973665412, 0.5134331453351957, 0.5810559726136121, 0.5684926350975337, 0.6125402492396689, 0.9289869625201223
+600, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4
+, 0.1378365503565375, 0.050594717687005665, 0.12781834109421955, 0.08752773884720516, 0.049670070100221224, 0.07664827304436632, 0.046105225891738925, 0.02153118141988729, 0.03233228014945535, 0.0604699995627281, 0.053891025109674896, 0.06548772677419284, 0.15524097503420448, 0.20322318539844983, 0.2685506473941544, 0.3672922083066144, 0.4728367869025848, 0.5215150279053673, 0.5827726312548501, 0.5019429810469788, 0.6236707269413359, 0.6381821952554616, 0.5617610775185542, 0.6050454853873801, 0.6781155911224431, 0.6977041177757346, 0.7921057139590649, 0.6326622936336238, 0.8560845234345356, 0.8638521228076326, 0.9234678570523027, 0.5228541729414256, 0.7057173072099404
+800, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8
+, 0.012317541353916594, 0.006880746923185741, 0.0018860052516560708, 0.09200540112678679, 0.03267249789183022, 0.07654308724863221, 0.13111551917418324, 0.11110315232892057, 0.2858352233385768, 0.3183838804941956, 0.3214764152349552, 0.5381027132381613, 0.5154858992781721, 0.5938759396466544, 0.5317669156056538, 0.474571014220306, 0.6656176259936978, 0.4470667687414132, 0.5694015228099887, 0.5721682279897327, 0.8456605579912806, 0.6845196622874592, 0.701356537506164, 0.9379461680382511, 0.47849324750243555
+1000, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.03673099779274436, 0.05975508700856275, 0.11729622266401589, 0.07431155893971492, 0.20129024254078534, 0.4122602456482906, 0.6700041328568925, 0.4307533654784136, 0.43106406500951033, 0.4362086337224014, 0.4358870724581107, 0.5947155769405055, 0.5170772477786677, 0.6550101981782633, 0.42172408225949354, 0.6801152737752161, 0.5717836886325366, 0.8028045185803616, 0.5636513233075834, 0.32157261133978665, 0.7451205510907003, 0.25624149496885484, 0.030797703222132593
+10000000, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.8
+, 0.0062919463087248335, 0.024701523260601082, 0.2840737382895135, 0.0578473552912253, 0.07021063189568708, 0.436086646036658, 0.5269060018126795, 0.3787509834038887, 0.4402173913043479, 0.578105949559571, 0.6284310137501962, 0.7335907335907337, 0.45416143979928836, 0.7206038447930181, 0.9030250931270212, 0.6380443086325439, 0.7962851491959756, 0.7771192021827078, 0.4714806276492899, 0.3111369584181448, 0.5469497035762096
+E
+200, -4.4, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.8
+, 0.009621440371994583, 0.004146270499067931, 0.027007253515549435, 0.03136727179124811, 0.038744876752604566, 0.016229285222223038, 0.03822370326896233, 0.03570001601652651, 0.04401784840638429, 0.05086975856820555, 0.07644960546391222, 0.06614806173185703, 0.061318793235008814, 0.10185835962162645, 0.1450144368887007, 0.1425492047876539, 0.20799587783194384, 0.19641586610839798, 0.2043744860695266, 0.2275087023393559, 0.2756277828898441, 0.3308814934337169, 0.4129586159308165, 0.48035942769144885, 0.5342480296805483, 0.5657700139485319, 0.6110696594264812, 0.6158626562381674, 0.6120291915122046, 0.6455192674095419, 0.6780413894925083, 0.6495724311929135, 0.6361403433588055, 0.7950927440077705, 0.5949832111286862, 0.37058920504165416, 0.3524209038075929, 0.5271389454687425, 0.7803589040683762, 0.47464831353328946
+400, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.017589676152591112, 0.06683204264988173, 0.01657213629129284, 0.00332003136981703, 0.00930518388267171, 0.005974036257469811, 0.017903762602890994, 0.03761496143931975, 0.03408447798140072, 0.07714241431466798, 0.10029575266470864, 0.09561574949799023, 0.14597655312457017, 0.15454703000082912, 0.17666151890870305, 0.18425024121949826, 0.20492924164637813, 0.27328431284733345, 0.35372364617784047, 0.45535119003288305, 0.5450906270210514, 0.5819563761275088, 0.6164230496799653, 0.6272027332867812, 0.6065517245120872, 0.5779706100641258, 0.6540444997527108, 0.5860082895169939, 0.6757729762046188, 0.5782390265906364, 0.6483029111399775, 0.7238765375054353, 0.8145822355514108, 0.38720430152211993, 0.29944373638984595, 0.26181929584821206
+600, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.053283575664541366, 0.03616471216877128, 0.06326608218206026, 0.011131203387245636, 0.028527095216323052, 0.014063364780183754, 0.045519433969399455, 0.10546598100346138, 0.14949350502179756, 0.15101877591261562, 0.09738810031195794, 0.13481415571820254, 0.14257886566448752, 0.2860309312905558, 0.3680760044864281, 0.4681448135606153, 0.5807334464914079, 0.5840788193716014, 0.5684825986445871, 0.5423637974395175, 0.6322784178809525, 0.5910884453929658, 0.4403967228080618, 0.7715571363898848, 0.6055828711644718, 0.7943209953485183, 0.44098092121701576, 0.8394721618942949, 0.771295161426513, 0.28710576355040146, 0.07682020988610647, 0.011131203387245636
+800, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.03430651347512906, 0.01170316774637141, 0.02172101047389925, 0.006417685703626693, 0.008803131942231902, 0.02558597050998453, 0.07306274568825875, 0.11280115830989065, 0.09350632912488134, 0.19757784784170848, 0.13668996284243146, 0.10109885106932971, 0.21372922331058639, 0.33935195047966055, 0.4835653244772779, 0.5933154629689057, 0.5389606803781795, 0.5486205951197954, 0.6256878350116513, 0.4954150416424488, 0.6982028550061831, 0.7725732080733803, 0.7556245509596634, 0.820419992617725, 0.3871956296488177, 0.21161330536631878
+1000, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4
+, 0.007075408536552707, 0.052106342694856415, 0.054267687080583535, 0.11138738604476046, 0.18238487903712933, 0.13756590467213264, 0.20171268632711103, 0.3204675946135979, 0.4939881373188593, 0.48725191860865325, 0.4577231292051552, 0.5029274757637503, 0.5911749097279292, 0.617890908127232, 0.6754028092464903, 0.7538926271666511, 0.7790160448683208, 0.9317881518423954, 0.2815681472036956
+10000000, -1.2, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.05348182058279778, 0.033963789927669706, 0.16707500121047786, 0.16511036477645546, 0.17236127301119492, 0.10153344754105208, 0.5210622228521675, 0.5405779170203302, 0.6467331482363765, 0.5613844499745355, 0.4960746174216681, 0.6196549070937729, 0.5823067577399326, 0.6626260661097897, 0.3857996700919029, 0.2655828409440213, 0.7804169453620828, 0.6799529670918482, 0.14494194369333543
+K
+200, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.8, 4.0
+, 0.006233425622353032, 0.030408921119546396, 0.02093592220185473, 0.03558424628095059, 0.010346048488097845, 0.005378266919520889, 0.03131994736626652, 0.028487448042530204, 0.03379094987238925, 0.024700449398553797, 0.03347424071928632, 0.07302434835089781, 0.073512659195887, 0.09610703764665972, 0.10795809398583348, 0.12494848067773846, 0.15366097022715058, 0.19623704670279507, 0.20948968747096094, 0.24338255490000843, 0.2906241049173688, 0.33876574586758207, 0.4184822248111851, 0.47928225866895335, 0.5290089476862202, 0.5603050017954271, 0.5786006171900762, 0.5901574708056799, 0.6223281637221282, 0.628128623412185, 0.5921857112354082, 0.6140101201683108, 0.5920359569841578, 0.5965921083365542, 0.6087237791828294, 0.4924534069623098, 0.38684136208760095, 0.8267798205668004, 0.052443291913803605, 0.13555614153669435, 0.4949704158969042
+400, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.6
+, 0.020798610371752655, 0.005632200186423676, 0.020798610371752648, 0.017012541269074165, 0.006032073496491691, 0.01364226026152598, 0.021143675648025915, 0.01868251927506294, 0.025685901851698386, 0.05158053569829252, 0.06125362327569112, 0.10431760125648461, 0.11657963235000496, 0.16124223048718866, 0.16595610614723216, 0.20943134871276328, 0.2710357434275307, 0.3346119224884066, 0.4332968718252851, 0.5110259226245114, 0.5749134438517876, 0.6081320558919092, 0.5874087675618509, 0.6035394962722405, 0.6231341763893807, 0.5835358073444723, 0.5961581174202724, 0.5709563638636703, 0.5779902811937659, 0.6074718329071743, 0.659698021432162, 0.5065478271339936, 0.8797381245584289, 0.7417154908480318, 0.44066114867280576, 0.3040791284756775, 0.15208479719465084, 0.0783083282618651
+600, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.08005202718154787, 0.04962009188671522, 0.039406216500345155, 0.002740406190104946, 0.011403405751254717, 0.0028098082516713977, 0.0071633756207432455, 0.03306075603501498, 0.0646831514898025, 0.11569513004064116, 0.13990454263335425, 0.17679877588621143, 0.16262258352799974, 0.1706813596201359, 0.2931339965678484, 0.43799455936872084, 0.5507332991803784, 0.6083433873274956, 0.6506958124282605, 0.5950317952941324, 0.5577837159753122, 0.6396812143891745, 0.6025343792533054, 0.41729136641693454, 0.5159270205746278, 0.550689666206242, 0.6076331037708719, 0.5624524359539496, 0.6696235241307377, 0.8959934752809087, 0.07262822815281679, 0.13051495642939867
+800, -2.2, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.018911760605919804, 0.004795965261657025, 0.045975193728396195, 0.008989657476380065, 0.017318826511208574, 0.025057718947206414, 0.12261710593295176, 0.11213161725895983, 0.19187686131466689, 0.14188715644056538, 0.14546530966094284, 0.31206534648850154, 0.47086768089542014, 0.545789218740381, 0.5885204739595565, 0.5773710383535828, 0.46045973024930353, 0.5908802815580871, 0.626959762836653, 0.6316980119840698, 0.664414162678641, 0.79310547563987, 0.33278822567457084, 0.7061514195583597, 0.15356389927792902, 0.054667562122229715
+1000, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.02052890441228883, 0.04023189215617797, 0.07663031858028652, 0.20025096556556882, 0.18400997644450603, 0.18611930275336508, 0.21527083749750153, 0.3970930399563381, 0.4481132941803083, 0.5686396636354857, 0.5301579703207275, 0.621978803891937, 0.7140332311751852, 0.6286470990555741, 0.6377560435504707, 0.7720935141696131, 0.8320930630399452, 0.3946962688868332
+10000000, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.6
+, 0.01260629568849769, 0.01879100107483044, 0.09267256151895265, 0.04568967070994719, 0.09962589275592335, 0.11544315827770806, 0.28789943693289816, 0.2591618348295238, 0.3929734264526971, 0.39127635602768385, 0.5935754756602113, 0.6145883983450332, 0.3876823250131941, 0.6618930447590909, 0.6606724003127443, 0.5138853185066581, 0.5624084011945034
+T
+200, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.008187665742003893, 0.028861201409083426, 0.00980913610487576, 0.1083985994398448, 0.0598706444724795, 0.05947128234147885, 0.16040484993339152, 0.09915598512252316, 0.10446723349172699, 0.1200298989675841, 0.15094705758522858, 0.1328601676913035, 0.07572629791473424, 0.12872358724292082, 0.14537735848143038, 0.18757394078969675, 0.20983017792030184, 0.2754583875906324, 0.3381900390309666, 0.40271265447333354, 0.4729359584475696, 0.5373178412824395, 0.5595641713342255, 0.6104980864110142, 0.6378975434547939, 0.6441654366086963, 0.6732334439933628, 0.666053356346672, 0.6774517895349775, 0.6637156928572294, 0.606772055426944, 0.6491227745638032, 0.6968486954506264, 0.6098259501108972, 0.6265547114255277
+400, -3.0, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.0027025687608381557, 0.004064194112156794, 0.0016032875228119338, 0.009757997483425634, 0.007868980509490626, 0.007607238389344213, 0.02595046601655586, 0.01905911002852271, 0.031882814581105576, 0.04062653475175, 0.08168889317790175, 0.1302149726190696, 0.17840065319707346, 0.2606656745972047, 0.39450792466149653, 0.4911094546024143, 0.5585520055189517, 0.5923224948870527, 0.6302384579809271, 0.6457682162071837, 0.6946071862394861, 0.7185853742529493, 0.7454414752360349, 0.618499419222971, 0.7074628958097988, 0.7352779958711105, 0.6955516339755666, 0.726348989935302, 0.31671773573998374, 0.40958798265579704
+600, -2.8, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8
+, 0.052328852070039164, 0.026867396031232334, 0.16837658222176605, 0.024245798575350842, 0.0262292817988048, 0.12130083036303745, 0.0613620195234056, 0.060587459883910885, 0.05055444507030803, 0.07451277195194778, 0.07160801588372659, 0.09814403889181059, 0.23180293729028179, 0.37716308908081375, 0.5000132531217487, 0.5844300853732715, 0.588706451584414, 0.6364889102697228, 0.6447154143653666, 0.6571490187910064, 0.7745048328842353, 0.6898685260527815, 0.5933031009014547, 0.8136253894039864, 0.737081747390056, 0.612229773163282, 0.8993016606028706, 0.17838061372014036
+800, -2.6, -2.2, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.8
+, 0.021818989702759535, 0.021818989702759535, 0.026069027674035287, 0.01465256116221214, 0.029619466548546323, 0.011029824666793777, 0.019680030570921273, 0.03947987072242306, 0.0986257950403479, 0.18456806333044862, 0.3139427691570446, 0.4815565268749844, 0.6261430195281782, 0.5140415380874448, 0.5665602405952214, 0.5992870215665328, 0.6250365102046636, 0.8048492147720124, 0.6377275954637704, 0.5701006015265965, 0.8557024286413152, 0.9530038501783763, 0.8085467849780019, 0.27882798691668526
+1000, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.4
+, 0.009332428725528, 0.04925965308388099, 0.07181890841950693, 0.1406860776336484, 0.259162393696497, 0.601915813203475, 0.5614990245451659, 0.5400938444987884, 0.6009355243934302, 0.5240251717766059, 0.5904347159672351, 0.7086467981563515, 0.6532544497183701, 0.7830103565979136, 0.8442480557193919, 0.6152519207547671
+10000000, -1.4, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.2
+, 0.017400075652502834, 0.013968671710909226, 0.016258931051023752, 0.02276972220938904, 0.07144236497729933, 0.25014108242074024, 0.6377278912714578, 0.6213497886400078, 0.8644058949419727, 0.43810672452330535, 0.5254430132270977, 0.8481163148765324, 0.3798431831480397, 0.7667171569008974, 0.8092008618156888, 0.5447444189442937
+N
+200, -4.2, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.0712065157005121, 0.13294638271304174, 0.024918407202641813, 0.3991956150411048, 0.0953625460996715, 0.022620790870142397, 0.07653812401707984, 0.04013908322757407, 0.06637157555040195, 0.08790716077730971, 0.06987895197872204, 0.11594595731928202, 0.09469654486442684, 0.1055032820197743, 0.11677327019941976, 0.1383930868361456, 0.17556655708200233, 0.21274981636519386, 0.24681031402251496, 0.275707492383167, 0.343676483955714, 0.41361073312621865, 0.49954020026571794, 0.5289597425675846, 0.5644353295028, 0.594018016380281, 0.6394736076806113, 0.664612890069819, 0.6676529289997108, 0.6609569315008057, 0.7241923463576184, 0.6799056719677031, 0.6618977735500067, 0.7626413640672547, 0.5363488878232969, 0.7741958263705373, 0.6860956762633909, 0.7969009695833165, 0.7827637598777691
+400, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4
+, 0.001128461356220943, 0.007744997057307509, 0.007104165781121, 0.012715233504607883, 0.01992997097665505, 0.010023506476345678, 0.008734440583315614, 0.012766891527232208, 0.037250387032780934, 0.03554618185109885, 0.0641277000435746, 0.10383126855713888, 0.15817420705543073, 0.1590150077356472, 0.19733501123405667, 0.2655449837641665, 0.33774475148059496, 0.42156779664100374, 0.49403682221432815, 0.5567834425997928, 0.5869474638861647, 0.598529564395528, 0.6427745755499635, 0.6511468650484329, 0.656275764390928, 0.7339886223828026, 0.7133697636691161, 0.7833908369222597, 0.7814001135653762, 0.6921926967996985, 0.6930677127575958, 0.8719006330411663, 0.6993407299981116, 0.7520194008570942
+600, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4
+, 0.012861627109688046, 0.05731785655357574, 0.07991944732610307, 0.08479562252863253, 0.08630884538516512, 0.06730490514845179, 0.008611336673529002, 0.024364202282699095, 0.04027411837341045, 0.05638279176751919, 0.07866817897417579, 0.07014008024714515, 0.1488228079108204, 0.21117858715982965, 0.22492604700759586, 0.3527511628371557, 0.4612776292791651, 0.508376750438461, 0.5978425447842742, 0.6169494954975383, 0.5870009692193582, 0.6834443025176401, 0.7503292713151367, 0.6041252831156599, 0.7114403688322494, 0.7942233006410815, 0.8025344848026892, 0.480061963819044, 0.8510863288832535, 0.4311453569540338, 0.4549099721194074, 0.8294748061125389, 0.3232898151906798
+800, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2
+, 0.019989818428644154, 0.023892261719647902, 0.0029054710661450957, 0.004062937593554483, 0.008984136668700427, 0.010308406280718847, 0.08691527710437, 0.10361026893347543, 0.04789619477114294, 0.16745026833775423, 0.21747643195160038, 0.20845806212626344, 0.32694891534008996, 0.47723349576907653, 0.5295067551508112, 0.5770392423901299, 0.5730686049665393, 0.5894890079270304, 0.6047381214895978, 0.6682541217110526, 0.7311441820863821, 0.652518439576027, 0.8361938939030221, 0.4820988922476904, 0.7577299982101305, 0.5925855581398125, 0.12158342006740268, 0.9351822615425827, 0.12598320331575102
+1000, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8
+, 0.08803701255783213, 0.09574103749053965, 0.08474819481634101, 0.17517515123980776, 0.26799302520655116, 0.28439407716762816, 0.41648646362717917, 0.5455595697137675, 0.5615697118402637, 0.6793471491223992, 0.6046007911293165, 0.5491817816902066, 0.49692743170413184, 0.7221889848936341, 0.5269348636773619, 0.7588655952688864, 0.47213759827611784, 0.4709761521355724, 0.643696648197198, 0.20472622478386168
+10000000, -1.4, -1.2, -1.0, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 2.0, 2.2, 2.4
+, 0.011076077289999191, 0.021909483447944987, 0.019761832256823684, 0.1397123465907093, 0.42129914368169563, 0.0812885393899792, 0.40490640849438697, 0.445164695597671, 0.5457577680850202, 0.6138506965124918, 0.499762804469091, 0.6076612903225806, 0.6718496818294005, 0.36172655263459996, 0.30939476061427285, 0.7177078765779696, 0.6569729941950139, 0.7172609072522392
+G
+200, -4.4, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0
+, 0.04980271364834668, 0.08033718293586467, 0.02137202174972912, 0.23924182209704178, 0.04290368826652217, 0.10995998186386532, 0.09077215489621959, 0.020063069662946225, 0.05199866894271401, 0.09869248618709753, 0.05755910536963877, 0.07335095177942563, 0.07836111992160895, 0.10947432785061317, 0.1829574600664543, 0.19644932151930236, 0.2475476355976773, 0.28047029664287276, 0.3663585502825831, 0.41381370184743865, 0.45028476809894513, 0.49271429268477074, 0.5257516371642744, 0.5380569146271968, 0.5816939874640986, 0.569518767778985, 0.5743891432518737, 0.5686338321658405, 0.6140459068175762, 0.5643093026733956, 0.6011486020284298, 0.573474665378709, 0.5168116740045788, 0.5321248352677072, 0.5278162040229152, 0.4301895642957476, 0.4371969736562028, 0.28501611757799006, 0.6434525427174271, 0.28996678413494487, 0.08989837533651014, 0.2567539583435563, 0.04184963224881832
+400, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4
+, 0.013901301934598695, 0.004289024917785121, 0.013437974346902313, 0.007368860439472664, 0.01073447463708951, 0.02777219816300249, 0.017735008916501906, 0.03167632189935238, 0.065395714271814, 0.08023970903915105, 0.11154164414214832, 0.2022512296813042, 0.25545491618906413, 0.3536476783862624, 0.42363655299206915, 0.4684936278546968, 0.4921050743779281, 0.5494874471369424, 0.558926685575915, 0.5687086639940497, 0.6215795839689724, 0.6083484928768131, 0.6314576358198148, 0.6230514702472063, 0.5920065807809958, 0.626983997044515, 0.6050340178513397, 0.5291775304616348, 0.49878218646796507, 0.47333053527490554, 0.5819171331727555, 0.5436606285875814, 0.7368953451348795, 0.21159919104802896, 0.2423277350632243
+600, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.004262592522543604, 0.009609989324161305, 0.040722908138649094, 0.017614076524928034, 0.0093627162404978, 0.015355034655796965, 0.024755600324803256, 0.020194055025720813, 0.026706288439159422, 0.08077741729614026, 0.12928457280333558, 0.2529615159130915, 0.34196845700567596, 0.45149860216958276, 0.40996695404314654, 0.42578108033137246, 0.4803786191950474, 0.5843776520341477, 0.5586147764363851, 0.617306728496986, 0.6227856958198603, 0.6671398928615958, 0.6500952347555135, 0.6889882325738811, 0.6256734694615649, 0.5995168124878059, 0.7490707491628702, 0.5011582262180214, 0.5080490865168124, 0.28843898542192936, 0.6652919608969325, 0.7408142102868135
+800, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.0020230132774187795, 0.023747698329704935, 0.028075380703131567, 0.015626043218693486, 0.04235468455893636, 0.09197490603136489, 0.18883534980280212, 0.27670832943186874, 0.4442895339785569, 0.36389293680452, 0.5494049531835955, 0.4340033509928248, 0.6029975424434239, 0.5363372195839183, 0.574020584323784, 0.5723823552003017, 0.668482030254807, 0.4580004693100662, 0.7116840257389728, 0.5822536180791649, 0.4377759423870536, 0.6468675879501711, 0.7183741297796663, 0.6254979951414307, 0.5158137378302833, 0.7279496888294327, 0.2627362326894526
+1000, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.006489542114188809, 0.006949859307726209, 0.022534370804249342, 0.04516393000377678, 0.1136821257633273, 0.5110285116517171, 0.46770290612880394, 0.3659219700856653, 0.4583001142462624, 0.41336563823768924, 0.397921392614628, 0.39534194552429375, 0.4342297564398891, 0.5579332833345442, 0.6046583720178514, 0.41123271903157327, 0.6403926457323382, 0.6698778696734571, 0.5480418899094861, 0.7586576713030415, 0.7548134802193488, 0.6548685078706759, 0.9440873569829723, 0.7717038041572167, 0.23724929693196156
+10000000, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2
+, 0.021380286118534823, 0.027108017567662453, 0.1482481505468543, 0.600664441493963, 0.6398889295975626, 0.37057797159012834, 0.7850458683916712, 0.614502459890595, 0.3122958193267364, 0.8122341869514071, 0.5943585978600379, 0.7604878736966307, 0.5587283184181798, 0.6866167554855552, 0.4973986404656242, 0.780872442534018, 0.7371014288730907, 0.30209092437916923
+M
+200, -3.4, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.02845963128097755, 0.006327814220719094, 0.03532321766363078, 0.02785817915545463, 0.06305230492182508, 0.06525558678224297, 0.06920333364821739, 0.09663310690550701, 0.09168272875852655, 0.10444060917510496, 0.14161496195972897, 0.18760094354688894, 0.27340880409079077, 0.3140034341765975, 0.3341867951289014, 0.3632541277201427, 0.39668565401586187, 0.43522081815108804, 0.47207835629148115, 0.5026342064038121, 0.5554008469913351, 0.5833574566458571, 0.6008099311783961, 0.6450861919646963, 0.6497380418171971, 0.7249028494100742, 0.7645552091301733, 0.7775959306800271, 0.7826666371582449, 0.7687189766034876, 0.7377750773840379, 0.8546113117648433, 0.7309510025155838, 0.5922461289520015
+400, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.038170835425479464, 0.01826291926366975, 0.008627909268057714, 0.005990921954905756, 0.007691489978484118, 0.020392739300842774, 0.04472291093102174, 0.060316255940233786, 0.06302004459220394, 0.1541038418593209, 0.22685507146016778, 0.2784664330885808, 0.29825937959171117, 0.3196733796620143, 0.3640325566040108, 0.40625749304857856, 0.4479345337346429, 0.5468608319197934, 0.5597030539512597, 0.6165686331561653, 0.6632688548164488, 0.6959674881486, 0.7903394987481768, 0.7268668913376479, 0.8235451001308638, 0.8275484601484625, 0.8098358326580584, 0.8637631783068633, 0.7737756627826707, 0.8647890997855323, 0.6977375511994904, 0.5247504661744165
+600, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2
+, 0.005736237861731748, 0.009523975244624639, 0.023891194668858876, 0.025234750802993748, 0.02552717930757656, 0.056254640669280716, 0.20941928914694077, 0.19788347655830058, 0.29589811372140384, 0.29852413139321216, 0.2897028729418557, 0.39073179258287705, 0.4552629356841357, 0.5593966833420538, 0.5750394291646366, 0.585085568055378, 0.7318672657089549, 0.6941092464581831, 0.8819680496498116, 0.8406532752846406, 0.8451650670206011, 0.9416795740780045, 0.893085997768151, 0.9110602722058794, 0.7163256112121613, 0.7174375236482226
+800, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.4, 3.8
+, 0.004674108580720676, 0.0035096825949236417, 0.02573551674322442, 0.08020943690055882, 0.2141222710358276, 0.3552257946322249, 0.323221883037281, 0.334294250957123, 0.2829357833432641, 0.43434992803525485, 0.5808355469054186, 0.6241893673747914, 0.6931880921298325, 0.5795185281057724, 0.5509178962895578, 0.8197337451110486, 0.736948316454277, 0.7846023423062995, 0.6580624097643196, 0.9191076830846109, 0.9023948888700153, 0.9474981632934666, 0.016170424235835836, 0.21365134335027647
+1000, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 3.4, 3.8
+, 0.0395955810122565, 0.20251297074083224, 0.2515696605044113, 0.23118137403932495, 0.31920693493675995, 0.32386507072905335, 0.5120874998766078, 0.5880070517335512, 0.7408938081106, 0.6469459262991496, 0.40303988237456356, 0.8411104193700822, 0.9040742300533903, 0.7482458141989218, 0.7670674781862866, 0.9574210199417486, 0.23437245866088377, 0.1630415456646714
+10000000, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.2
+, 0.005278592375366569, 0.02483900643974241, 0.21079571893904142, 0.25278114329772, 0.24822695035460993, 0.39404962972586727, 0.8361985706007341, 0.5839568257083283, 0.5340659340659342, 0.7478816708785491, 0.435701214440193, 0.7346019028542814, 0.5848733325174398, 0.5098265895953757
+W
+200, -4.0, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0
+, 0.010053137251715156, 0.03614107661201093, 0.07513752318069507, 0.06232763609362001, 0.04090719053394041, 0.03012721074281631, 0.01999689051399049, 0.020024382749013706, 0.035560145033910834, 0.041624797523196214, 0.06142487113870969, 0.07038694508427773, 0.0874141479196364, 0.14373224227628087, 0.1930317693688374, 0.17608850960040795, 0.2837591992712456, 0.31751427975693, 0.37402457119572285, 0.3767044103235768, 0.3875467674943792, 0.5162805569385304, 0.5513809807468663, 0.43645713565312544, 0.5295897770124752, 0.5509452638284295, 0.6355399448481385, 0.6292792289200955, 0.6154280980913217, 0.5862191648292456, 0.692729444731882, 0.6933688155617883, 0.6525897180760073, 0.6862900638687898, 0.6206267900753528, 0.7227963137333674, 0.6563610741001843, 0.6541491631508591, 0.6862278523667734, 0.5173986502301023, 0.6254962352564359, 0.2376686434766528, 0.2850520026378816, 0.32445331851643955, 0.1545443294828597
+400, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.2
+, 0.003936305168090178, 0.002892443565021887, 0.008130955780809584, 0.012686225767031701, 0.025774402091606103, 0.04458131185056105, 0.05957848834895015, 0.09030918669627554, 0.1253577531298458, 0.1762117242340049, 0.18978784602769633, 0.2613781994982344, 0.3479702350864556, 0.38339977058667163, 0.38746151324205624, 0.4143832977912655, 0.4326335523770048, 0.48109640926677794, 0.5253077885613805, 0.5436337693892012, 0.5957468274559441, 0.6066920552022064, 0.5856318907005583, 0.7405960813443107, 0.6556337756952331, 0.7700481180232187, 0.6123487455485063, 0.716084361648064, 0.5946136429487322, 0.7631646331908402, 0.7287205565301803, 0.7089736280501816, 0.7458023147425407, 0.800312812064102, 0.7905807458117725, 0.7524453487016617, 0.6904598548976143, 0.09244951222078437, 0.8853441973001723, 0.22803862653375243
+600, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8
+, 0.015941116115818707, 0.016594307129943656, 0.010924353018042558, 0.014218984649465553, 0.02534885725861216, 0.06771148595573359, 0.06116471271630187, 0.058466868227181355, 0.11369094282044122, 0.10028915633745711, 0.09713241672842075, 0.23121690042026713, 0.21175385468088415, 0.28462241635242436, 0.31685345966888984, 0.34243553290584766, 0.3967943463270171, 0.5322292663560987, 0.46053074781033976, 0.46756551159626847, 0.5093913642584738, 0.46665721497662693, 0.5872387559719567, 0.5295263318218335, 0.6679207002526416, 0.633194898204035, 0.8205977787023934, 0.6778801000144382, 0.6386241437433336, 0.7474959665347901, 0.7280984639756457, 0.792440375474518, 0.8269539563283489, 0.914446352387371, 0.6292990018576369, 0.9002209011938572, 0.8814371535125446, 0.9569213613893796, 0.5613551803722755, 0.15303410010373106
+800, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0
+, 0.0224761653850587, 0.06897795528325656, 0.043964184488533876, 0.05426990516042012, 0.10593446276907946, 0.11088933395600369, 0.11131403251399657, 0.41212081201518397, 0.252185523895901, 0.5131779640168599, 0.4970442274474704, 0.3753445990025042, 0.4454367118169079, 0.43641127627008697, 0.5375555342059549, 0.582743847296434, 0.700875716747453, 0.3693056263810981, 0.5166424534068959, 0.5938453539126746, 0.5650094444620126, 0.7110946731164166, 0.6077794715264038, 0.797757938175236, 0.5455658878175588, 0.673111514092521, 0.7037020400243812, 0.6435682203777798, 0.604048928630185, 0.8674003285619997, 0.2236593996887986, 0.928303029180713
+1000, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.6
+, 0.05041657765434737, 0.02326957207651351, 0.03004073319755601, 0.19675712971481144, 0.3266965127238455, 0.22095951443145867, 0.36550759392486015, 0.7630891680139287, 0.6041852181656279, 0.8423339540657977, 0.6174986823281381, 0.39799453053783046, 0.7304563141139018, 0.6849573328041277, 0.3470302731161567, 0.3593023674822529, 0.4835460460460461, 0.7854439789160697, 0.6272501956691886, 0.6353194544149319, 0.8131345333267939, 0.6726479627242986, 0.9429828499595941, 0.7991883202445581, 0.6992572398895678, 0.5080599505378266, 0.8768982229402262, 0.4046968016124748, 0.8114981199287552, 0.3381969775924961
+10000000, -1.0, -0.8, -0.6, -0.4, -0.2, 0.4, 0.6, 0.8, 1.0, 3.0, 4.0, 4.2
+, 0.0021122338299937207, 0.1448140900195695, 0.07805907172995782, 0.28139773895169584, 0.22224694104560624, 0.16373639516804211, 0.3721264367816092, 0.3226118969192017, 0.33218720152817577, 0.0726298477372805, 0.4892249251223611, 0.8037608756665732
+D
+200, -4.6, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8
+, 0.018626895228895723, 0.11728080320078006, 0.5937426667262748, 0.03927533862645874, 0.05974671976524982, 0.0917149470704997, 0.06046434414289128, 0.04459964351175079, 0.03891584428680007, 0.05454776436988832, 0.05760795314793352, 0.06520214434682021, 0.08441878992655659, 0.10554307834242026, 0.13156414894978147, 0.14638211055267963, 0.17598859363160593, 0.17217531685054885, 0.18463737353117532, 0.20794269423656211, 0.27808363911099476, 0.3642544766197776, 0.42615125908706963, 0.5026779437159384, 0.5381913735877556, 0.5448344936741886, 0.5736658815321012, 0.5728175734848698, 0.5772159313301718, 0.5935206601384001, 0.5785927893804083, 0.5803030006598179, 0.634696992284186, 0.6632184597205736, 0.5725772600179964, 0.5806805560809384, 0.6456153291100302, 0.4008137326056845, 0.5142766154383125, 0.594144624446019, 0.9480860255395239, 0.7891323212963747
+400, -3.8, -3.6, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8
+, 0.017526022053705452, 0.010090662246000215, 0.005911072408159453, 0.0094242912522625, 0.00483203212764107, 0.014840210378253412, 0.035251055138788005, 0.03010333597027076, 0.05707110978001972, 0.06806654215390828, 0.10122954326734433, 0.13770152403508962, 0.1251534611085536, 0.15864699520014003, 0.12863271934388903, 0.17303911256916327, 0.23872337803608437, 0.3438374233682127, 0.4471077553553215, 0.5299235923012301, 0.5563624942893748, 0.5662502058564726, 0.5721638839165779, 0.6129871191897227, 0.5660340347563402, 0.6308606276684164, 0.632643587440431, 0.5798265428394158, 0.5711256183324998, 0.6104867833858457, 0.5477759251339209, 0.5034780015525244, 0.28633253697579686, 0.6019606099741027, 0.41753839461241327, 0.34898716933495605, 0.1753443010109411, 0.4937170887940028
+600, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.07572055697912322, 0.04685137919874146, 0.013470059859080275, 0.016120642626666723, 0.025934741332931405, 0.013470059859080279, 0.01047103161086878, 0.043184882720677706, 0.07524094553614041, 0.057131662342132405, 0.07555065450499734, 0.09094351900345422, 0.07943708440995989, 0.14120981974737906, 0.15889063869132145, 0.18288901171356836, 0.2994462254923587, 0.455922970640683, 0.470865053294829, 0.555923147176361, 0.5744394407250271, 0.5983652427055746, 0.6451298402584105, 0.6144094316369362, 0.5638708071261487, 0.5817023571301216, 0.7382954315694873, 0.6415137553013202, 0.6027798778331301, 0.5498240561188864, 0.3129098587277003, 0.5853527174502478, 0.6417674076529638, 0.34646976044148603, 0.8892401221593547, 0.06589683307979534
+800, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 3.0, 3.2
+, 0.008510660029390252, 0.053999319540527856, 0.029166739590808066, 0.11008787306416677, 0.06867749030405805, 0.10487922755985372, 0.08441754322657907, 0.13927445001053515, 0.1262502840915484, 0.1581350088904876, 0.37032405294594306, 0.47112296199708115, 0.5059968009083806, 0.5667473589508149, 0.5662007078489808, 0.5036665508717231, 0.5685524410133438, 0.5021030771387083, 0.46777863494735494, 0.6249417586714079, 0.6570922695616377, 0.7799387736421073, 0.7624247583463559, 0.364603814519136, 0.8518129178326466, 0.33007532508626103, 0.2808647177027291
+1000, -2.0, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.03099074564389641, 0.03526188187699943, 0.0601183779288754, 0.10708870906841245, 0.14124632869365342, 0.07858307490648676, 0.16099733636085756, 0.11251951702527954, 0.31888428435752014, 0.3845687605484582, 0.47978895233223035, 0.5356864443869647, 0.5760458574570188, 0.5243609252477301, 0.44676271680565494, 0.5517489421762919, 0.40731563845050217, 0.5530463031664227, 0.7056189995435903, 0.6602700897805741, 0.7555583244746631, 0.43490969602040125, 0.9630958463140022
+10000000, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.4, 2.6
+, 0.0014151021012620737, 0.01120977596741344, 0.04853957951178213, 0.06924634213674427, 0.2242589254898953, 0.3488169966199903, 0.4214279585474444, 0.5540891613841836, 0.6191275770879868, 0.5765505268784041, 0.7524044757887831, 0.70228140959197, 0.36758525047113005, 0.6752083232984923, 0.8562413388764525, 0.4384222653499529, 0.2229776446185757, 0.7973201791445547, 0.13059610618454792, 0.0663917127836773
+H
+200, -4.0, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0
+, 0.03366143791073794, 0.12229579473890749, 0.0023965874294210304, 0.11142894439620184, 0.0598821754984208, 0.035073646976856346, 0.030033608637588124, 0.042770531837719, 0.07436799354604083, 0.06192889876940986, 0.07501889297412434, 0.07651922461089912, 0.10236657357048272, 0.13008490869476172, 0.17570521982550932, 0.19562570288549183, 0.2402717212537774, 0.34894741760751985, 0.3926314534309388, 0.463459973122341, 0.4872892573845177, 0.5656076053978417, 0.5702410891638474, 0.5842610000246314, 0.6401215021032886, 0.6635057656919326, 0.6858272882551264, 0.7036437455064729, 0.6900683507603625, 0.7912016521539376, 0.6256905279756557, 0.6551663451279496, 0.6442387019495477, 0.5154430296772594, 0.610714922104654, 0.47655815437182536, 0.5038680884987706, 0.331638615368125, 0.16532032785248002
+400, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0
+, 0.024983509456821706, 0.0023065782730348084, 0.02498350945682171, 0.03938325596225074, 0.01924885711675501, 0.017001918349411307, 0.004532697766235948, 0.01672786076537002, 0.030488464144219574, 0.04246194666294303, 0.05482530743289866, 0.09453774664211397, 0.15068238595070957, 0.22043514025408253, 0.30862698998080434, 0.40606922105192056, 0.4635111004362203, 0.5490011391057846, 0.5896936531471226, 0.6012522032441759, 0.6334213044527051, 0.6530489917577715, 0.6816836432220428, 0.7235863198736988, 0.6104989855312881, 0.744281538492875, 0.6437700766365099, 0.6596101401847652, 0.6237587050584414, 0.4909123749450153, 0.4754536332396059, 0.5319185585373064, 0.5738471453688846, 0.5770204247077545, 0.3974957524720365, 0.12628946646351794
+600, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8
+, 0.003375360767234541, 0.02315851530668037, 0.007713013203962888, 0.020489809218885796, 0.02789797627428184, 0.05670945810086781, 0.08172911385087334, 0.10354699727263074, 0.20946023963686963, 0.3485166802620737, 0.4135052949447255, 0.5048283954868971, 0.5810659272872755, 0.6252028870513755, 0.49276922092287434, 0.6972373542165986, 0.598283244541968, 0.7060471943352125, 0.6335714820846869, 0.8409656287721421, 0.8713022883991768, 0.7548429339870076, 0.7731077709300429, 0.6286562667563377, 0.7416134578437232, 0.7973583875768113, 0.6246797630480752, 0.44839283867200974, 0.618207741949151
+800, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.004332254797836343, 0.008517472428799602, 0.02801288412634691, 0.04042976376212141, 0.05638253860440923, 0.1485878639312434, 0.45494966839303996, 0.5364218471499814, 0.6019752585827106, 0.6468967344018158, 0.7291083814949837, 0.5541234821386483, 0.44092351636485544, 0.5412120458980819, 0.5492062498043022, 0.6146558441172213, 0.46263676380203994, 0.8097888157180061, 0.8253314552869299, 0.9025689021252576, 0.3065145430410163, 0.887952826612005, 0.7349291853455371, 0.6930569512214189, 0.7189787433389939
+1000, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 3.0, 3.2, 3.4
+, 0.016726572227312234, 0.044336969269249515, 0.06230922176482117, 0.2733652504290111, 0.3606353085893688, 0.4154854412512842, 0.4931667421477475, 0.5421469025922283, 0.5483236455497511, 0.569378907839295, 0.43122599932991407, 0.506119714597294, 0.4286583086215133, 0.6048992306603105, 0.45424657023908194, 0.6333345687706163, 0.5822196798974196, 0.8918964292632531, 0.9422988109598484, 0.8579332348997845
+10000000, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 2.0, 2.4, 3.0, 3.4
+, 0.026043125175021, 0.28627129078596353, 0.2006741486957521, 0.3602109329490757, 0.5126121076233183, 0.7521644636049453, 0.7345747319418476, 0.4402735868034601, 0.7231112172597723, 0.4617557163307154, 0.4887361728712654, 0.6417756720568545, 0.36683051156016755, 0.3773720014321518, 0.6682563906905762
+F
+200, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.8
+, 0.0118796572796037, 0.0014672582394740575, 0.03743998420606895, 0.027945978849726678, 0.042221213889387516, 0.010801552826949386, 0.04139522496607944, 0.03999191502135917, 0.05211549995458061, 0.060297109638310954, 0.10129384648254204, 0.15616351789120644, 0.21318276089539578, 0.25042509461225854, 0.29299384438800996, 0.30431199722184266, 0.31474465593677153, 0.3215608071222106, 0.34933410952686794, 0.4013372334166951, 0.4132461627252968, 0.4735993600214136, 0.5137798275706204, 0.5240892505076316, 0.5732127691892553, 0.5728471386016757, 0.587424087598907, 0.6378341853871199, 0.6652131586082336, 0.6434091755890186, 0.6811145001725185, 0.6778946461924046, 0.6531231489646425, 0.622114029030299, 0.7027944481835392, 0.6544984744633467, 0.6768972298187619, 0.7649999212127353, 0.17747727606580532, 0.03200371938741867
+400, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4
+, 0.004521502078034196, 0.011294546197758165, 0.01902181455153136, 0.028453600912992427, 0.045494587204780265, 0.075636622645322, 0.1346817828927533, 0.1858370410511906, 0.21145461364683354, 0.22993300300255923, 0.24758097664369763, 0.2503946720700768, 0.2893435384653396, 0.33294847977837494, 0.3801325469321394, 0.4218741104610451, 0.4797481604447298, 0.511808478587414, 0.5974117622187544, 0.5834704269428962, 0.6578279478883984, 0.6933440994726486, 0.7200687227206225, 0.6742670559283108, 0.7199198750632219, 0.7264408323450363, 0.7378516949019436, 0.8038271425512616, 0.8296853580700081, 0.8243729580366167, 0.779678703055898, 0.7171620329790568
+600, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.04225844325367724, 0.02996073852825442, 0.0033279267524589365, 0.010538147174194904, 0.0055842967220071866, 0.023707193295361365, 0.03287914981492101, 0.055581517092584964, 0.12205147623150721, 0.18674255469804368, 0.21228362626337297, 0.19176664697425205, 0.192771021747899, 0.2738504396168108, 0.2706484536269102, 0.3113119235107976, 0.3768631860175106, 0.4286865380951811, 0.4674373782473765, 0.4470173830795746, 0.5654578562715549, 0.6089083108990303, 0.6950018580809499, 0.754745539388691, 0.6729932052759504, 0.6466101067600745, 0.7630081242628347, 0.7653017355343918, 0.7660715915354379, 0.9006582480689912, 0.8613792472553212, 0.9183691145965688
+800, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.0025284892240452768, 0.0013041538615920674, 0.02322344999575436, 0.06274762646486995, 0.14440845571763275, 0.3574106974338475, 0.26027269066425, 0.2629704658055164, 0.24533138237707777, 0.26347140721903634, 0.3022788001575987, 0.29989143373704513, 0.4442104934598845, 0.5365972904585126, 0.4221062978051718, 0.5554972868238451, 0.5400155429805876, 0.6527242876757253, 0.47262603008218756, 0.6000342893579687, 0.8297108914342853, 0.5432571765506535, 0.6164512733317686, 0.659729845987438, 0.878226507885687, 0.8293156239699597, 0.39935167691260115
+1000, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8
+, 0.06957581181214641, 0.11727576980179334, 0.19879724787180408, 0.15514564994465022, 0.15335563242078185, 0.2029411563067941, 0.33025361900905537, 0.4179908587644115, 0.4428200805838054, 0.5634100755177667, 0.5680939840623824, 0.41520905829955296, 0.5753449870929177, 0.48414588902396805, 0.5913147768147112, 0.4648190251829891, 0.6358734895010334, 0.8449506822406887, 0.5716931289884855, 0.6013880377634973, 0.7021165582108326, 0.7605031088714594, 0.8316368363163683
+10000000, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.08665812891997504, 0.1893325561060915, 0.392884167636787, 0.7103372143883693, 0.1713556511117511, 0.12470072279692956, 0.2383403904279098, 0.4472355817003856, 0.3084458638141755, 0.3922429804435704, 0.5098120423323317, 0.4048967889635629, 0.4046453884579675, 0.45231916560612523, 0.578670933838637, 0.527791925571288, 0.9204796267282687, 0.9253331472075768, 0.8919738382028523, 0.8766760073779796, 0.8865785578260142
+Y
+200, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0
+, 0.009286499266584609, 0.04190994220311158, 0.005673267516690456, 0.011282526243736116, 0.041909942203111575, 0.05957785566189, 0.04749864096985896, 0.05803797548561103, 0.07284698771143527, 0.04867312515561958, 0.0837839451245465, 0.08136844795311347, 0.1196284938247924, 0.13488330074785607, 0.1859103414172193, 0.22494333273362108, 0.2845607850383266, 0.34148624354154694, 0.3537330507841197, 0.4303267700378927, 0.4596981968135125, 0.5043265158898462, 0.5722032966248287, 0.591132260747033, 0.5615672359144327, 0.6433527557582447, 0.6200821169061512, 0.6866199534656023, 0.6409420681507526, 0.6377669951160809, 0.6475917264147603, 0.5867402271820585, 0.6081464300418282, 0.5855598936277712, 0.703751153709795, 0.5335558858652032, 0.5718292411383575, 0.7868125143340565, 0.5943859446876695, 0.2531795538962151
+400, -3.0, -2.8, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8
+, 0.0024631904120060435, 0.014599337728464305, 0.0019080473895611095, 0.0034467235991527422, 0.007898872470056247, 0.02454940809416175, 0.02767901585092433, 0.060144475081240587, 0.10182673535143302, 0.1402223895256354, 0.2159272947456956, 0.2474628127234784, 0.30672796698809546, 0.3701837946270894, 0.4281630341544478, 0.4900105528169095, 0.49672558077846896, 0.5458230184672949, 0.5822237283945346, 0.6232035400297948, 0.6309651873689367, 0.6650089068472502, 0.6906883232556257, 0.719070120561808, 0.5861318306017409, 0.6939528630753063, 0.644733589945717, 0.7557826365261244, 0.7868872016335692, 0.8077101821427416, 0.785137848061695, 0.7007336361374807, 0.7907789335787568, 0.9314640234622172
+600, -3.2, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8
+, 0.0678339420637355, 0.03132907113746549, 0.19521471211245917, 0.0790468441438464, 0.04504147115901855, 0.03621970390869113, 0.03736078959794541, 0.0702121913978338, 0.07678045932576472, 0.10633802477667664, 0.11960413292539095, 0.19900688668929817, 0.19847870369671886, 0.35052340230366474, 0.4182620478260756, 0.49334638007139636, 0.4139336918612302, 0.4758803364739189, 0.48058197497143446, 0.5325837123233392, 0.6764738640938338, 0.5824113213410999, 0.6854925565305252, 0.716699831685794, 0.6913247110998257, 0.7364537742437196, 0.6973151529206393, 0.6640017089879244, 0.7535147537884177, 0.8736524217431264, 0.8883154079240142, 0.9086524895242979, 0.3364614429341759, 0.8892455486542443, 0.516276512630574
+800, -2.4, -2.2, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4
+, 0.12499249996999987, 0.017542677750980205, 0.004183814710350362, 0.04049577780196881, 0.01945394480279348, 0.05981555656515628, 0.1662287133765109, 0.2470726136520115, 0.2279836885745909, 0.3405906596146762, 0.39304167365159454, 0.5479494843905584, 0.5776797970134353, 0.4969350548999451, 0.554976031602476, 0.6111452872519451, 0.5933613225870421, 0.6503765957046587, 0.6459187382843162, 0.47697114639093807, 0.4439174984783494, 0.5898786001485177, 0.6521583574634947, 0.699411044781371, 0.8755290078823845, 0.6892194962693724, 0.5956513541689771, 0.4191972780617089, 0.6859665367471306
+1000, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4
+, 0.01513420581891473, 0.04710716529773664, 0.08675346730823665, 0.2536586494224809, 0.34051794477036007, 0.4949352227554531, 0.3744979625153848, 0.3885763166955366, 0.47500620176957165, 0.6732234245582497, 0.5916145874535242, 0.6141509220860845, 0.7235237614799357, 0.8444622025111802, 0.5840380724187212, 0.37117416203862574, 0.6845523703789804, 0.7343493349470799, 0.6147306746541727, 0.836192015818726, 0.6897855770617488, 0.7497181598163127, 0.3071472030349666, 0.1919103374866947
+10000000, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 2.0, 2.2, 2.6, 2.8, 3.0, 3.2
+, 0.0708645474792468, 0.17151110308719983, 0.2570225856067352, 0.11678972600342932, 0.14007308160779536, 0.5103673933918981, 0.7576957600718095, 0.7229533929002657, 0.7098140887820918, 0.6723469072042269, 0.6112883643448062, 0.6166996129966311, 0.893002867868218, 0.8895255061508461, 0.8001654763978401, 0.30475369142377656, 0.6623003900213408, 0.7044407947702315, 0.6821802063854838
+C
+200, -4.4, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8
+, 0.00552600427650797, 0.03485954094930549, 0.03838810402982251, 0.025715627803848534, 0.025488221431905482, 0.04343408489770449, 0.07142970187382498, 0.061574074307699386, 0.07314774143241341, 0.0645623004653657, 0.08295448119612607, 0.11583376897861364, 0.10923780472615427, 0.15872284777216678, 0.18960300191746962, 0.21632285501348175, 0.2689843145563964, 0.317374224275957, 0.3630447998094276, 0.47533324924738357, 0.47607691305922323, 0.5079450745840531, 0.5277576798975776, 0.5628057172760719, 0.575051710042101, 0.5593880195311266, 0.6755090738783593, 0.5934386213582137, 0.6382467809460037, 0.46977743056505733, 0.49332782901573397, 0.433919671579876, 0.4787946054736947, 0.5285187386448856, 0.5192055844835611, 0.5418864058012781, 0.4974690811553878, 0.6669903566100355, 0.5635741644172909, 0.5631278587090643, 0.4509635087812499, 0.41102196954637915, 0.5675101424562242, 0.3858209367335479, 0.7158058178212813, 0.8441831930348846, 0.917028268187617
+400, -2.8, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4, 4.6, 4.8, 5.0, 5.2
+, 0.010395396838634843, 0.021361460299502484, 0.02165535066430582, 0.015159525108778021, 0.05264200337595036, 0.09707983819746174, 0.09731511297628698, 0.14129374581890802, 0.20022262624150677, 0.1899999623811763, 0.24177069784075372, 0.2794320762962471, 0.3349563341527679, 0.39941588667848116, 0.37542427668497114, 0.4413948575311084, 0.4994511731980783, 0.5229578236619977, 0.517824249985961, 0.5986188278934524, 0.55649711734287, 0.6546467413270598, 0.7295136272915, 0.6635498671850562, 0.6708303778437357, 0.6854662728780426, 0.7366769816589981, 0.6804239212899574, 0.8020315025334613, 0.648248800129263, 0.4883801068027809, 0.5457865193156772, 0.7435757599432814, 0.3888378116158756, 0.8142396988934587, 0.35653604110313064, 0.9515094757412567, 0.8683671258886828, 0.43063122020040623, 0.20134832264371375
+600, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2, 4.4
+, 0.014640944089221617, 0.047190998499466535, 0.016131092675076904, 0.05393342938205346, 0.03794117361550069, 0.14801529752994014, 0.12649865136882416, 0.12425487801283724, 0.18258838145967776, 0.17401252442552514, 0.24820371537628083, 0.2723009495881132, 0.31076828090971514, 0.4228592493350921, 0.4833419854280797, 0.48225822549606906, 0.6096979060194508, 0.6813975348841623, 0.6390568469900091, 0.6423882998985359, 0.6933120557029364, 0.7437104177397691, 0.7344965946599342, 0.5339314985180899, 0.76693091389901, 0.7860009499083788, 0.9485711375084455, 0.7614620936289629, 0.7922335003939941, 0.8140234673530409, 0.9905994173641781, 0.7496322833936753, 0.5402660706005019, 0.18423883691036483
+800, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 4.0, 4.2, 4.4
+, 0.1676606183648437, 0.1676606183648437, 0.07743155394424302, 0.07659036520366225, 0.040008410782623315, 0.06504823840581023, 0.1572369829786188, 0.20637862095592702, 0.26511828078110244, 0.26880018429549696, 0.7715955945577099, 0.5608321221346089, 0.5723698356275932, 0.5774648391346796, 0.5310722977083755, 0.5139787601877006, 0.6388370807266754, 0.5159175246850328, 0.4037730013428791, 0.6462677917648109, 0.6914477449297176, 0.7064353719025876, 0.6496598105159759, 0.8061020949745134, 0.9114250135029706, 0.805807135371541, 0.7069698372603644, 0.5579972241756949, 0.9707483336999887, 0.2521582668435688, 0.6737025368927209
+1000, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.6
+, 0.020481263776634836, 0.03747584236618773, 0.07963219211712719, 0.42117945879058266, 0.40087635526094045, 0.4186096119797778, 0.7519767441860465, 0.6969740019889189, 0.6769121710047986, 0.5095117468832265, 0.49996377012356535, 0.42357137893493324, 0.3704784074335224, 0.5022112276689343, 0.5377495655874323, 0.9377135348226019, 0.518641826827345, 0.6148997981190606, 0.925832429274806, 0.9306706710610997, 0.5275370793684547
+10000000, -0.6, 0.2, 0.6, 1.0, 1.2, 1.4, 2.2, 2.6, 2.8, 3.6
+, 0.2450956648098813, 0.34003811136989204, 0.5689392891716222, 0.5240494732020156, 0.4197691734921817, 0.6071833648393195, 0.47977746870653687, 0.1474288840262582, 0.2158490566037736, 0.059728506787330306
+I
+200, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6
+, 0.010246568324761396, 0.023586419611002423, 0.07326453667116309, 0.02266434565723754, 0.19125014334998405, 0.049215674536650926, 0.08042765604892763, 0.11504040934022898, 0.09190473758714221, 0.07884776581058621, 0.13204286686172295, 0.17339014874279796, 0.14738531701866997, 0.1925666588813994, 0.2798288367649437, 0.30356530000018567, 0.37802490411090917, 0.3891635072532392, 0.4188735667360788, 0.4130451708923584, 0.4090566074203953, 0.4005398324769401, 0.43727658014390886, 0.4525658021391098, 0.49469453336259855, 0.5364548074114078, 0.5487359041804901, 0.5589759259605349, 0.5600275134828192, 0.5857561779201617, 0.5950991838931297, 0.6171171951409766, 0.6208158282379346, 0.5341821673007862, 0.5911918922048982, 0.47767207984960436, 0.6016175443003301, 0.453017422332317, 0.009829615646825916, 0.011933949374280328
+400, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8
+, 0.009424041651289006, 0.005248090853102813, 0.020104435812286, 0.008380660947748239, 0.011633543757944554, 0.031233862457621414, 0.03796795304800285, 0.05304879411403409, 0.09428391079887828, 0.1957080355293911, 0.26417738982917194, 0.33722314135736386, 0.3835329367560942, 0.38791379723365044, 0.3469048845284936, 0.33981871326454166, 0.3718334747259479, 0.3744119941355528, 0.4371801106903041, 0.4742278199477808, 0.5467307808120919, 0.5889710925569661, 0.6003132839102469, 0.6282891377294968, 0.6667994100593078, 0.7149791981213757, 0.7165443100481403, 0.7648169965214152, 0.7931588888124155, 0.849697960723633, 0.5985009755051228
+600, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6
+, 0.01177149197646163, 0.019466387676539337, 0.009179617714196748, 0.021002809412977955, 0.012304705104874294, 0.01742489800381316, 0.09673996824968178, 0.20818513532059035, 0.24902690941466604, 0.3201033911616928, 0.3968527717263692, 0.32677150095038016, 0.2956502311222198, 0.3521918640702484, 0.34323878987875367, 0.41238085067793995, 0.4528202043089073, 0.4946606714015018, 0.60916176112803, 0.586244459052103, 0.731691655254136, 0.7615547888406847, 0.7532320282223522, 0.8256747853564931, 0.8227885041950739, 0.9414977098583945, 0.8707420724568614
+800, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4
+, 0.004884508436313263, 0.008895670331354973, 0.04738253012569462, 0.15700893886749803, 0.2720568723512916, 0.29754465051552165, 0.3529009205231974, 0.33901402505796213, 0.33151291774566327, 0.3171419785124146, 0.39610993206239475, 0.42435592249318754, 0.4284240846602554, 0.48610410052424313, 0.5011209748404598, 0.5923040805122267, 0.6801122435468188, 0.6003811302269592, 0.6886824799977288, 0.6536244005652843, 0.7340922067541863, 0.9749464234875972
+1000, -2.0, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2
+, 0.04006366374589266, 0.016420176967562962, 0.10541928765426886, 0.1842196914154018, 0.33370157870353867, 0.4140144214086954, 0.37627524716443256, 0.376828275689411, 0.350294020866546, 0.29056694294813423, 0.428977185963412, 0.4437891708347922, 0.4040640317539013, 0.5436759732095426, 0.6396942795183248, 0.699574241911313, 0.6264500766775059, 0.6958787809288652, 0.6647049856983595, 0.9007007532728866
+10000000, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0
+, 0.05928374933750602, 0.2840734480639214, 0.355188042763727, 0.4981825035676783, 0.522066931657905, 0.687219937903835, 0.4285758086769892, 0.26404535582320265, 0.4070341937448583, 0.31549829407614327, 0.3522842812258061, 0.41463591162408975, 0.44042322850815757, 0.8108811576260953, 0.6660499661785326, 0.6714949448238751, 0.6945054584794939, 0.9471616054797473
+P
+200, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.2
+, 0.09462093250004656, 0.06513499980673217, 0.25836149525869284, 0.003590843571806108, 0.08011419031573228, 0.03750805525576047, 0.0574609648224664, 0.021046661598639223, 0.03965651331683649, 0.03233547498093971, 0.05244949461037999, 0.059239211279768764, 0.08658427873468452, 0.11641077018764909, 0.17102302987730567, 0.21557776345358962, 0.3488992728757439, 0.38412126513874806, 0.4717518589355339, 0.48086303211958253, 0.5349972443434652, 0.5523284345890979, 0.5139727330404497, 0.5737275580736053, 0.646507295963126, 0.6177418767988746, 0.5913879649161384, 0.6113435859450091, 0.6248086488637173, 0.6177495838258914, 0.5915088103951179, 0.5390155146848349, 0.5544234138321293, 0.4961989976316854, 0.5910782276103086, 0.575955804525867, 0.8040228012576552, 0.2552364547730815, 0.1539699424587969, 0.6105382318958665, 0.6920195597291678
+400, -3.2, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4, 3.6, 4.0, 4.2
+, 0.027678544003005952, 0.0017759936101448578, 0.01563976484987035, 0.02662887534696838, 0.010267917113890223, 0.014499665143659572, 0.027299347695871414, 0.045885094521211214, 0.04395609633506502, 0.07075355873801675, 0.11122160543559785, 0.19482765066850968, 0.3102447121351171, 0.4323382675846813, 0.5049196275808877, 0.5340408301827624, 0.5699327744168944, 0.5646308086676382, 0.5898440411347238, 0.5960532705788892, 0.6456568185067169, 0.6761301863788893, 0.6705221804706994, 0.6794427710153623, 0.6560926262495437, 0.6670270517403344, 0.6415870485838746, 0.4940385904199614, 0.5459239564924565, 0.47599332002445893, 0.409220079384302, 0.42847584927258375, 0.827666355527503, 0.6427397436884055, 0.3387975859228055, 0.6658481930242676
+600, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2, 3.4
+, 0.054115861337130235, 0.046296087292164195, 0.056336173545012996, 0.005138426504631574, 0.03016715284976033, 0.02195661225379361, 0.035469037639700524, 0.043213639799410224, 0.07923069137404684, 0.1892981614814477, 0.24008662810215636, 0.4542352013348483, 0.5155927001365727, 0.6227024593529396, 0.6069408758206023, 0.5689367573494439, 0.6173067228915726, 0.6507688014522729, 0.5604747283213789, 0.7005841663886421, 0.6021972001890809, 0.7322327525953377, 0.6256764860648757, 0.6644107146326537, 0.6404289926815111, 0.5798792570169877, 0.48913332794575626, 0.4739894981973522, 0.6169184160982089, 0.6311019946564094, 0.9162938262863316
+800, -2.4, -2.2, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.2
+, 0.00625109691006886, 0.0036866050811829405, 0.010821473610371099, 0.034581709047270474, 0.052505947010089406, 0.04046046640914797, 0.0715445762534076, 0.19387348265185214, 0.3024834157149413, 0.4407693068754491, 0.5501948550333603, 0.4344640358714685, 0.4429962655179792, 0.4559017802592965, 0.4550889515888062, 0.562065860749629, 0.5872819382503642, 0.5031074411074145, 0.549570630011202, 0.7331689607663807, 0.637804892388616, 0.7508243979930967, 0.6847389871555631, 0.6837776185382219, 0.7089342805159007, 0.7548686754100637, 0.6858453269953747, 0.737874223470343
+1000, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.09319850573232, 0.10979172199248835, 0.06948530038214824, 0.07586792624252905, 0.1989606990626378, 0.3974041167469781, 0.4836987107065937, 0.43529270200348963, 0.5872083609038189, 0.4748060743676909, 0.4782649923500425, 0.47660581529267176, 0.40493349371783804, 0.4729478286637323, 0.5031491548381056, 0.4918696117603916, 0.474799166651737, 0.7606885434541573, 0.6515931714096899, 0.8523660209056383, 0.6549542201339508, 0.49738075923608915, 0.37358200278550074, 0.9102043744992286, 0.30461699146099175
+10000000, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.2, 0.4, 0.6, 0.8, 1.0, 1.4, 1.6, 1.8, 2.0, 2.4, 2.8, 3.0
+, 0.002034225211333397, 0.03213966868366234, 0.1254929577464789, 0.22886329058900245, 0.5338868536424239, 0.30411880078453357, 0.7558683600047184, 0.8943652386947497, 0.5068308181096108, 0.8747794169548951, 0.808677163898561, 0.6541717723070068, 0.520123659549802, 0.8308427892277724, 0.75944364805703, 0.46422176679969807, 0.11903193440828615, 0.9246754822273444
+V
+200, -4.2, -4.0, -3.8, -3.6, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0
+, 0.3013177924972648, 0.0670576962538446, 0.027947536968587417, 0.025471567022443797, 0.17738326284128084, 0.10698026054520915, 0.027192326456929903, 0.04736489830728461, 0.15565145058718088, 0.08889759595104872, 0.0901815261535527, 0.12890229680120277, 0.17640442149470179, 0.20057478536198106, 0.25497736014857153, 0.2845496101729879, 0.3387008081814645, 0.36859541367677057, 0.408859593377653, 0.42852982770728926, 0.43491545736005727, 0.4437173153173867, 0.4307511980475097, 0.4688229717283917, 0.5041690529385188, 0.5206150940885195, 0.5504178549950146, 0.604449454781223, 0.5852695922917379, 0.5892740759521515, 0.5821242214118382, 0.611738803380447, 0.5748701424067844, 0.5470664583475426, 0.4366875437443472, 0.2990467205099567, 0.17194313586429896
+400, -3.4, -3.2, -3.0, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 3.0
+, 0.007630710431630884, 0.05643138079149608, 0.0019464106682222882, 0.00495914554400256, 0.008471384625919275, 0.022434103491537804, 0.040253776825090605, 0.025356097618350212, 0.048630164072312, 0.06994433785325964, 0.10054807768512329, 0.17714681726250375, 0.262931751831555, 0.34550802640469575, 0.3781959689270546, 0.43546932456834325, 0.4111227842326892, 0.39342474726021504, 0.40754351242412284, 0.460087545031051, 0.4784670790288331, 0.5272787211953236, 0.5658096821582352, 0.6095502530391147, 0.6572364343932448, 0.6458428060835956, 0.699498928622632, 0.7675563268175648, 0.7165153170099512, 0.5393942384511748, 0.5587490608280018, 0.7684784086894817
+600, -2.8, -2.6, -2.4, -2.2, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4
+, 0.061032997065434115, 0.18533639985747144, 0.0145577041202563, 0.010942786101539745, 0.07387934237880509, 0.037536176376309634, 0.02763024311231824, 0.02265328277135838, 0.09520478453610436, 0.1595129075059143, 0.22597260291075094, 0.37063686634929416, 0.4028000965396746, 0.40189585160555535, 0.32174279329124866, 0.37195239626061044, 0.4539851836669101, 0.4666124404448917, 0.5233672984387059, 0.5443786020355682, 0.670588238862655, 0.6746727393780464, 0.774273657653073, 0.8059482440811514, 0.7534118409082837, 0.933769318652744, 0.9199396810574295
+800, -2.0, -1.8, -1.6, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4
+, 0.008536139445826405, 0.010647452272946844, 0.003065442904427912, 0.004083085051204419, 0.017935306813610788, 0.09716361787367706, 0.19725368574759128, 0.3505081624049802, 0.4204715759928817, 0.45469008403510625, 0.388999422485893, 0.32305500994632613, 0.39140601027418337, 0.48052658276599364, 0.421967881355336, 0.5799579944888391, 0.619119965966238, 0.619504925624972, 0.6769064254531707, 0.7778709874558832, 0.771651999854801, 0.7479361219585633, 0.5246872402663989
+1000, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2
+, 0.03892955516942246, 0.12043398243351962, 0.2645304545541721, 0.4365200127998329, 0.437088025611357, 0.35702064605615885, 0.4010590154472944, 0.36781079834103564, 0.4587836912312046, 0.39663279275577046, 0.6365005914806564, 0.5655098255829267, 0.593426197811947, 0.6692760067022221, 0.8622693278223753, 0.7184982472426565, 0.7060497525545142
+10000000, -1.4, -1.2, -1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 2.0
+, 0.017728944142882157, 0.007167824432547233, 0.08493880095308559, 0.2528489732042521, 0.4813898894916351, 0.36070591557949294, 0.39824076805492237, 0.3119042195275812, 0.32650985724376896, 0.49659876345439163, 0.5211131565504622, 0.4260184611915101, 0.5637321616051639, 0.5428210040346628, 0.7687209074612477, 0.7000895494459963, 0.8891690518938169
index fdd15cd..2647c43 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
@@ -59,6 +60,8 @@ action.boxes = Boxes
 action.text = Text
 action.by_pairwise_id = By Pairwise Identity
 action.by_id = By Id
+action.by_evalue = By E-Value
+action.by_bit_score = By Bit Score
 action.by_length = By Length
 action.by_group = By Group
 action.unmark_as_reference = Unmark as Reference 
@@ -98,6 +101,7 @@ action.edit_group = Edit Group
 action.border_colour = Border colour
 action.edit_new_group = Edit New Group
 action.hide_sequences = Hide Sequences
+action.add_background_frequencies = Add Background Frequencies
 action.sequences = Sequences
 action.ids = IDS
 action.ids_sequences = IDS and sequences
@@ -131,6 +135,8 @@ action.select_highlighted_columns = Select Highlighted Columns
 tooltip.select_highlighted_columns = Press B to mark highlighted columns, Ctrl-(or Cmd)-B to toggle, and Alt-B to mark all but highlighted columns 
 action.deselect_all = Deselect all
 action.invert_selection = Invert selection
+action.filter_by_evalue = Filter by E-Value
+action.filter_by_score = Filter by Score
 action.using_jmol = Using Jmol
 action.link = Link
 action.group_link = Group Link
@@ -198,6 +204,9 @@ label.colourScheme_turnpropensity = Turn Propensity
 label.colourScheme_buriedindex = Buried Index
 label.colourScheme_purine/pyrimidine = Purine/Pyrimidine
 label.colourScheme_nucleotide = Nucleotide
+label.colourScheme_hmmer-uniprot = HMMER profile v global background
+label.colourScheme_hmmer-alignment = HMMER profile v alignment background
+label.colourScheme_hmm_match_score = HMM Match Score
 label.colourScheme_t-coffeescores = T-Coffee Scores
 label.colourScheme_rnahelices = By RNA Helices
 label.colourScheme_sequenceid = Sequence ID Colour
@@ -803,8 +812,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>
@@ -943,7 +952,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
@@ -1051,6 +1059,7 @@ exception.ranml_couldnt_process_data = Couldn't process data as RNAML file ({0})
 exception.ranml_invalid_file = Invalid RNAML file ({0})
 exception.ranml_problem_parsing_data = Problem parsing data as RNAML ({0})
 exception.pfam_no_sequences_found = No sequences found (PFAM input)
+exception.hmmer_no_valid_sequences_found = No valid sequences found
 exception.stockholm_invalid_format = This file is not in valid STOCKHOLM format: First line does not contain '# STOCKHOLM'
 exception.couldnt_parse_sequence_line = Could not parse sequence line: {0}
 exception.unknown_annotation_detected = Unknown annotation detected: {0} {1}
@@ -1124,6 +1133,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_search = 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}
@@ -1334,6 +1346,79 @@ 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.use_sequence = Sequence to use
+label.hmmbuild = hmmbuild
+label.hmmsearch = hmmsearch
+label.jackhmmer = jackhmmer
+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.inclusion_threshold = Inlcusion Threshold
+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.jackhmmer_options = jackhmmer 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.number_of_iterations = Number of jackhmmer Iterations
+label.auto_align_seqs = Automatically Align Fetched Sequences
+label.new_returned = new sequences returned
+label.use_accessions = Return Accessions
+label.check_for_new_sequences = Return Number of New Sequences
+label.evalue = E-Value
+label.reporting_seq_evalue = Reporting Sequence E-value Cut-off
+label.reporting_seq_score = Reporting Sequence Score Threshold
+label.reporting_dom_evalue = Reporting Domain E-value Cut-off
+label.reporting_dom_score = Reporting Domain Score Threshold
+label.inclusion_seq_evalue = Inclusion Sequence E-value Cut-off
+label.inclusion_seq_score = Inclusion Sequence Score Threshold
+label.inclusion_dom_evalue = Inclusion Domain E-value Cut-off
+label.inclusion_dom_score = Inclusion Domain Score Threshold
+label.number_of_results_desc = The maximum number of hmmsearch results to display
+label.number_of_iterations_desc = The number of iterations jackhmmer will complete when searching for new sequences
+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.check_for_new_sequences_desc = Display number of new sequences returned from hmmsearch compared to the previous alignment 
+label.use_accessions_desc = If true, the accession number of each sequence is returned, rather than that sequence's name
+label.reporting_seq_e_value_desc = The E-value cutoff for returned sequences 
+label.reporting_seq_score_desc = The score threshold for returned sequences 
+label.reporting_dom_e_value_desc = The E-value cutoff for returned domains 
+label.reporting_dom_score_desc = The score threshold for returned domains 
+label.inclusion_seq_e_value_desc = Sequences with an E-value less than this cut-off are classed as significant
+label.inclusion_seq_score_desc = Sequences with a bit score greater than this threshold are classed as significant
+label.inclusion_dom_e_value_desc = Domains with an E-value less than this cut-off are classed as significant
+label.inclusion_dom_score_desc = Domains with a bit score greater than this threshold are classed as significant
+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
+action.search = Search
 label.backupfiles_confirm_delete = Confirm delete
 label.backupfiles_confirm_delete_old_files = Delete the following older backup files? (see the Backups tab in Preferences for more options)
 label.backupfiles_confirm_save_file = Confirm save file
@@ -1403,4 +1488,4 @@ label.by_annotation_tooltip = Annotation Colour is configured from the main Colo
 label.show_linked_features = Show {0} features
 label.on_top = on top
 label.include_linked_features = Include {0} features
-label.include_linked_tooltip = Include visible {0} features<br>converted to local sequence coordinates
\ No newline at end of file
+label.include_linked_tooltip = Include visible {0} features<br>converted to local sequence coordinates
index daa4418..d53272f 100644 (file)
@@ -868,7 +868,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
@@ -1335,6 +1334,7 @@ label.most_bound_molecules = M
 label.most_polymer_residues = Más Residuos de Polímeros
 label.cached_structures = Estructuras en Caché
 label.free_text_search = Búsqueda de texto libre
+action.search = Buscar
 label.backupfiles_confirm_delete = Confirmar borrar
 label.backupfiles_confirm_delete_old_files = Â¿Borrar los siguientes archivos? (ver la pestaña 'Copias' de la ventana de Preferencias para más opciones)
 label.backupfiles_confirm_save_file = Confirmar guardar archivo
index 1d2235e..c21721b 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 22c9098..53d767b 100644 (file)
@@ -34,6 +34,7 @@ package ext.edu.ucsf.rbvi.strucviz2;
 
 import jalview.bin.Cache;
 import jalview.gui.Preferences;
+import jalview.util.FileUtils;
 
 import java.io.File;
 import java.io.IOException;
@@ -935,18 +936,16 @@ public class StructureManager
     }
     else if (os.startsWith("Windows"))
     {
-      for (String root : new String[] { "\\Program Files",
-          "C:\\Program Files", "\\Program Files (x86)",
-          "C:\\Program Files (x86)" })
-      {
-        for (String version : new String[] { "1.11", "1.11.1", "1.11.2",
-            "1.12", "1.12.1", "1.12.2", "1.13" })
-        {
-          pathList.add(root + "\\Chimera " + version + "\\bin\\chimera");
-          pathList.add(
-                  root + "\\Chimera " + version + "\\bin\\chimera.exe");
-        }
-      }
+      /*
+       * typical Windows installation path is
+       * C:\Program Files\Chimera 1.12\bin\chimera.exe
+       */
+      // current drive:
+      pathList.addAll(FileUtils.findMatches("\\",
+              "Program Files*/Chimera*/bin/{chimera,chimera.exe}"));
+      // C: drive (note may add as duplicates)
+      pathList.addAll(FileUtils.findMatches("C:\\",
+              "Program Files*/Chimera*/bin/{chimera,chimera.exe}"));
     }
     else if (os.startsWith("Mac"))
     {
index f1d5e79..580c829 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 completeGapAnnot(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
@@ -719,4 +827,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 8473904..2d05865 100755 (executable)
@@ -86,6 +86,10 @@ public class AlignmentSorter
 
   private static boolean sortLengthAscending;
 
+  private static boolean sortEValueAscending;
+
+  private static boolean sortBitScoreAscending;
+
   /**
    * Sorts sequences in the alignment by Percentage Identity with the given
    * reference sequence, sorting the highest identity to the top
@@ -182,7 +186,7 @@ public class AlignmentSorter
     List<SequenceI> algn;
     synchronized (algn = align.getSequences())
     {
-      List<SequenceI> tmp = new ArrayList<SequenceI>();
+      List<SequenceI> tmp = new ArrayList<>();
 
       for (int i = 0; i < seqs.length; i++)
       {
@@ -268,6 +272,90 @@ public class AlignmentSorter
   }
 
   /**
+   * Sorts by sequence evalue. Currently moves all sequences without an evalue to
+   * the top of the alignment.
+   * 
+   * @param align
+   *                The alignment object to sort
+   */
+  public static void sortByEValue(AlignmentI align)
+  {
+    int nSeq = align.getHeight();
+
+    double[] evalue = new double[nSeq];
+    SequenceI[] seqs = new SequenceI[nSeq];
+
+    for (int i = 0; i < nSeq; i++)
+    {
+      seqs[i] = align.getSequenceAt(i);
+      AlignmentAnnotation[] ann = seqs[i].getAnnotation("Search Scores");
+      if (ann != null)
+      {
+        evalue[i] = ann[0].getEValue();
+      }
+      else
+      {
+        evalue[i] = -1;
+      }
+    }
+
+    QuickSort.sort(evalue, seqs);
+
+    if (sortEValueAscending)
+    {
+      setReverseOrder(align, seqs);
+    }
+    else
+    {
+      setOrder(align, seqs);
+    }
+
+    sortEValueAscending = !sortEValueAscending;
+  }
+
+  /**
+   * Sorts by sequence bit score. Currently moves all sequences without a bit
+   * score to the top of the alignment
+   * 
+   * @param align
+   *                The alignment object to sort
+   */
+  public static void sortByBitScore(AlignmentI align)
+  {
+    int nSeq = align.getHeight();
+
+    double[] score = new double[nSeq];
+    SequenceI[] seqs = new SequenceI[nSeq];
+
+    for (int i = 0; i < nSeq; i++)
+    {
+      seqs[i] = align.getSequenceAt(i);
+      AlignmentAnnotation[] ann = seqs[i].getAnnotation("Search Scores");
+      if (ann != null)
+      {
+        score[i] = ann[0].getEValue();
+      }
+      else
+      {
+        score[i] = -1;
+      }
+    }
+
+    QuickSort.sort(score, seqs);
+
+    if (sortBitScoreAscending)
+    {
+      setReverseOrder(align, seqs);
+    }
+    else
+    {
+      setOrder(align, seqs);
+    }
+
+    sortBitScoreAscending = !sortBitScoreAscending;
+  }
+
+  /**
    * Sorts the alignment by size of group. <br>
    * Maintains the order of sequences in each group by order in given alignment
    * object.
@@ -279,7 +367,7 @@ public class AlignmentSorter
   {
     // MAINTAINS ORIGNAL SEQUENCE ORDER,
     // ORDERS BY GROUP SIZE
-    List<SequenceGroup> groups = new ArrayList<SequenceGroup>();
+    List<SequenceGroup> groups = new ArrayList<>();
 
     if (groups.hashCode() != lastGroupHash)
     {
@@ -315,7 +403,7 @@ public class AlignmentSorter
 
     // NOW ADD SEQUENCES MAINTAINING ALIGNMENT ORDER
     // /////////////////////////////////////////////
-    List<SequenceI> seqs = new ArrayList<SequenceI>();
+    List<SequenceI> seqs = new ArrayList<>();
 
     for (int i = 0; i < groups.size(); i++)
     {
@@ -357,7 +445,7 @@ public class AlignmentSorter
     // tmp2 = tmp.retainAll(mask);
     // return tmp2.addAll(mask.removeAll(tmp2))
 
-    ArrayList<SequenceI> seqs = new ArrayList<SequenceI>();
+    ArrayList<SequenceI> seqs = new ArrayList<>();
     int i, idx;
     boolean[] tmask = new boolean[mask.size()];
 
@@ -436,7 +524,7 @@ public class AlignmentSorter
   {
     int nSeq = align.getHeight();
 
-    List<SequenceI> tmp = new ArrayList<SequenceI>();
+    List<SequenceI> tmp = new ArrayList<>();
 
     tmp = _sortByTree(tree.getTopNode(), tmp, align.getSequences());
 
index 55efaa5..c7ed332 100644 (file)
@@ -1465,28 +1465,31 @@ public class AlignmentUtils
       final List<AlignmentAnnotation> result = new ArrayList<>();
       for (AlignmentAnnotation dsann : datasetAnnotations)
       {
-        /*
-         * Find matching annotations on the alignment. If none is found, then
-         * add this annotation to the list of 'addable' annotations for this
-         * sequence.
-         */
-        final Iterable<AlignmentAnnotation> matchedAlignmentAnnotations = al
-                .findAnnotations(seq, dsann.getCalcId(), dsann.label);
-        if (!matchedAlignmentAnnotations.iterator().hasNext())
+        if (dsann.annotations != null) // ignore non-positional annotation
         {
-          result.add(dsann);
-          if (labelForCalcId != null)
+          /*
+           * Find matching annotations on the alignment. If none is found, then
+           * add this annotation to the list of 'addable' annotations for this
+           * sequence.
+           */
+          final Iterable<AlignmentAnnotation> matchedAlignmentAnnotations = al
+                  .findAnnotations(seq, dsann.getCalcId(), dsann.label);
+          if (!matchedAlignmentAnnotations.iterator().hasNext())
           {
-            labelForCalcId.put(dsann.getCalcId(), dsann.label);
+            result.add(dsann);
+            if (labelForCalcId != null)
+            {
+              labelForCalcId.put(dsann.getCalcId(), dsann.label);
+            }
           }
         }
-      }
-      /*
-       * Save any addable annotations for this sequence
-       */
-      if (!result.isEmpty())
-      {
-        candidates.put(seq, result);
+        /*
+         * Save any addable annotations for this sequence
+         */
+        if (!result.isEmpty())
+        {
+          candidates.put(seq, result);
+        }
       }
     }
   }
index fdca89d..61fc747 100755 (executable)
@@ -20,6 +20,8 @@
  */
 package jalview.analysis;
 
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
@@ -35,7 +37,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 +54,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 +71,16 @@ public class SeqsetUtils
               (seq.getDatasetSequence() != null) ? seq.getDatasetSequence()
                       : new Sequence("THISISAPLACEHOLDER", ""));
     }
+    if (seq.hasHMMProfile())
+    {
+      sqinfo.put("HMM", seq.getHMM());
+    }
+
+    if (seq.getAnnotation("Search Scores") != null)
+    {
+      sqinfo.put("Score", seq.getAnnotation("Search Scores"));
+    }
+
     return sqinfo;
   }
 
@@ -97,6 +109,10 @@ 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");
+    AlignmentAnnotation[] scores = (AlignmentAnnotation[]) sqinfo
+            .get("Score");
+
     if (oldname == null)
     {
       namePresent = false;
@@ -135,6 +151,18 @@ public class SeqsetUtils
       sq.setDatasetSequence(seqds);
     }
 
+    if (hmm != null)
+    {
+      sq.setHMM(new HiddenMarkovModel(hmm, sq));
+    }
+
+    if (scores != null)
+    {
+      for (AlignmentAnnotation score : scores)
+      {
+        sq.addAlignmentAnnotation(score);
+      }
+    }
     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 785dd14..e5bf0be 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();
 
   /**
@@ -113,6 +119,8 @@ public interface AlignViewportI extends ViewStyleI
 
   boolean isIgnoreGapsConsensus();
 
+  boolean isIgnoreBelowBackground();
+
   boolean isCalculationInProgress(AlignmentAnnotation alignmentAnnotation);
 
   AlignmentAnnotation getAlignmentQualityAnnot();
@@ -497,9 +505,23 @@ 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);
 
   /**
    * @param update
index 3bb5fe8..a44f1f9 100644 (file)
@@ -235,6 +235,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());
@@ -1323,6 +1324,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     {
       sortGroupMenuItem_actionPerformed();
     }
+    else if (source == sortEValueMenuItem)
+    {
+      sortEValueMenuItem_actionPerformed();
+    }
+    else if (source == sortBitScoreMenuItem)
+    {
+      sortBitScoreMenuItem_actionPerformed();
+    }
     else if (source == removeRedundancyMenuItem)
     {
       removeRedundancyMenuItem_actionPerformed();
@@ -2772,6 +2781,26 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
 
   }
 
+  public void sortEValueMenuItem_actionPerformed()
+  {
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
+    AlignmentSorter.sortByEValue(viewport.getAlignment());
+    addHistoryItem(new OrderCommand("Group Sort", oldOrder,
+            viewport.getAlignment()));
+    alignPanel.paintAlignment(true, false);
+
+  }
+
+  public void sortBitScoreMenuItem_actionPerformed()
+  {
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
+    AlignmentSorter.sortByBitScore(viewport.getAlignment());
+    addHistoryItem(new OrderCommand("Group Sort", oldOrder,
+            viewport.getAlignment()));
+    alignPanel.paintAlignment(true, false);
+
+  }
+
   public void removeRedundancyMenuItem_actionPerformed()
   {
     new RedundancyPanel(alignPanel);
@@ -3122,6 +3151,10 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
 
   MenuItem sortGroupMenuItem = new MenuItem();
 
+  MenuItem sortEValueMenuItem = new MenuItem();
+
+  MenuItem sortBitScoreMenuItem = new MenuItem();
+
   MenuItem removeRedundancyMenuItem = new MenuItem();
 
   MenuItem pairwiseAlignmentMenuItem = new MenuItem();
index 66bb7a5..e2c8d27 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.
  * 
@@ -56,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);
@@ -201,7 +207,7 @@ public class AlignViewport extends AlignmentViewport
                         colour));
         if (residueShading != null)
         {
-          residueShading.setConsensus(hconsensus);
+          residueShading.setConsensus(consensusProfiles);
         }
       }
 
@@ -212,15 +218,8 @@ public class AlignViewport extends AlignmentViewport
       }
     }
     initAutoAnnotation();
-
   }
 
-  java.awt.Frame nullFrame;
-
-  protected FeatureSettings featureSettings = null;
-
-  private float heightScale = 1, widthScale = 1;
-
   /**
    * {@inheritDoc}
    */
@@ -300,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 e9081b0..19ab59a 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 a0102b9..9cd2b51 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()
+                                                                                               .getIgnoreGapsConsensus()
                             : ap.av.isIgnoreGapsConsensus());
             final AlignmentAnnotation aaa = aa[selectedRow];
             cbmi.addItemListener(new ItemListener()
index 8f72260..c6eb507 100755 (executable)
@@ -69,7 +69,7 @@ public class OverviewPanel extends Panel implements Runnable,
 
     od = new OverviewDimensionsShowHidden(av.getRanges(),
             (av.isShowAnnotation()
-                    && av.getSequenceConsensusHash() != null));
+                                               && av.getSequenceConsensusHash() != null));
 
     oviewCanvas = new OverviewCanvas(od, av);
     setLayout(new BorderLayout());
index ca2a584..d6da405 100755 (executable)
@@ -107,7 +107,7 @@ public class Jalview
         perms.add(new AllPermission());
         return (perms);
       }
-
+    
       @Override
       public void refresh()
       {
@@ -124,8 +124,8 @@ public class Jalview
   class FeatureFetcher
   {
     /*
-     * TODO: generalise to track all jalview events to orchestrate batch processing
-     * events.
+     * TODO: generalise to track all jalview events to orchestrate batch
+     * processing events.
      */
 
     private int queued = 0;
@@ -202,8 +202,6 @@ public class Jalview
     System.out.println(System.getProperty("os.arch") + " "
             + System.getProperty("os.name") + " "
             + System.getProperty("os.version"));
-    // report Jalview version
-    Cache.loadBuildProperties(true);
 
     ArgsParser aparser = new ArgsParser(args);
     boolean headless = false;
@@ -328,8 +326,7 @@ public class Jalview
     }
 
     /*
-     * configure 'full' SO model if preferences say to, else use the default (SO
-     * Lite)
+     * configure 'full' SO model 
      */
     if (Cache.getDefault("USE_FULL_SO", true))
     {
index 3b0ca46..70a3cc2 100755 (executable)
@@ -291,6 +291,32 @@ public class Alignment implements AlignmentI, AutoCloseable
   }
 
   /**
+   * 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!
@@ -1620,7 +1646,7 @@ public class Alignment implements AlignmentI, AutoCloseable
     annot.hasText = false;
     if (calcId != null)
     {
-      annot.setCalcId(new String(calcId));
+      annot.setCalcId(calcId);
     }
     annot.autoCalculated = autoCalc;
     if (seqRef != null)
@@ -2029,4 +2055,18 @@ public class Alignment implements AlignmentI, AutoCloseable
     }
   }
 
+  @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 2ee4503..3e532df 100755 (executable)
@@ -94,6 +94,10 @@ public class AlignmentAnnotation
    */
   private long invalidrnastruc = -2;
 
+  private double bitScore;
+
+  private double eValue;
+
   /**
    * Updates the _rnasecstr field Determines the positions that base pair and
    * the positions of helices based on secondary structure from a Stockholm file
@@ -584,7 +588,7 @@ public class AlignmentAnnotation
     }
     return null;
   }
-
+  
   /**
    * Creates a new AlignmentAnnotation object.
    * 
@@ -696,7 +700,7 @@ public class AlignmentAnnotation
       }
     }
   }
-
+  
   /**
    * Copy constructor creates a new independent annotation row with the same
    * associated sequenceRef
@@ -729,6 +733,9 @@ public class AlignmentAnnotation
     this.scaleColLabel = annotation.scaleColLabel;
     this.showAllColLabels = annotation.showAllColLabels;
     this.calcId = annotation.calcId;
+    this.bitScore = annotation.bitScore;
+    this.eValue = annotation.eValue;
+
     if (annotation.properties != null)
     {
       properties = new HashMap<>();
@@ -960,6 +967,7 @@ public class AlignmentAnnotation
    * @param seqRef
    * @param startRes
    * @param alreadyMapped
+   *          - annotation are at aligned columns
    */
   public void createSequenceMapping(SequenceI seqRef, int startRes,
           boolean alreadyMapped)
@@ -1161,7 +1169,7 @@ public class AlignmentAnnotation
   {
     return hasScore || !Double.isNaN(score);
   }
-
+  
   /**
    * Score only annotation
    * 
@@ -1192,6 +1200,7 @@ public class AlignmentAnnotation
     makeVisibleAnnotation(hidden);
   }
 
+
   public void setPadGaps(boolean padgaps, char gapchar)
   {
     this.padGaps = padgaps;
@@ -1651,7 +1660,6 @@ public class AlignmentAnnotation
           Iterable<AlignmentAnnotation> list, SequenceI seq, String calcId,
           String label)
   {
-
     ArrayList<AlignmentAnnotation> aa = new ArrayList<>();
     for (AlignmentAnnotation ann : list)
     {
@@ -1696,7 +1704,6 @@ public class AlignmentAnnotation
   public static Iterable<AlignmentAnnotation> findAnnotation(
           List<AlignmentAnnotation> list, String calcId)
   {
-
     List<AlignmentAnnotation> aa = new ArrayList<>();
     if (calcId == null)
     {
@@ -1714,4 +1721,24 @@ public class AlignmentAnnotation
     return aa;
   }
 
+  public double getBitScore()
+  {
+    return bitScore;
+  }
+
+  public void setBitScore(double bitScore)
+  {
+    this.bitScore = bitScore;
+  }
+
+  public double getEValue()
+  {
+    return eValue;
+  }
+
+  public void setEValue(double eValue)
+  {
+    this.eValue = eValue;
+  }
+
 }
index 93a2456..7386d4b 100755 (executable)
@@ -518,8 +518,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
    */
@@ -604,6 +602,16 @@ public interface AlignmentI extends AnnotatedCollectionI
   public boolean 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.
    */
@@ -623,5 +631,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 e6604d1..c00f0b1 100644 (file)
@@ -25,6 +25,7 @@ import jalview.util.ShiftList;
 
 import java.io.PrintStream;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -114,6 +115,16 @@ public class AlignmentView
     {
       return seqs.size();
     }
+
+    public SequenceGroup getNewSequenceGroup(char c)
+    {
+      SequenceGroup newsg = new SequenceGroup(sg);
+      for (SeqCigar seq : seqs)
+      {
+        newsg.addSequence(seq.getSeq(c), false);
+      }
+      return newsg;
+    }
   }
 
   /**
@@ -1237,4 +1248,21 @@ public class AlignmentView
     }
 
   }
+
+  /**
+   * return pruned visible sequences in each group in alignment view
+   * 
+   * @param c
+   * @return
+   */
+  public Collection<? extends AnnotatedCollectionI> getVisibleGroups(char c)
+  {
+    ArrayList<SequenceGroup> groups = new ArrayList<>();
+    for (ScGroup sc : scGroups)
+    {
+      SequenceGroup sg = sc.getNewSequenceGroup(c);
+      groups.add(sg);
+    }
+    return groups;
+  }
 }
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..6b8b095
--- /dev/null
@@ -0,0 +1,672 @@
+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;
+
+  // stores background frequencies of alignment from which this model came
+  private Map<Character, Float> backgroundFrequencies;
+
+  /**
+   * 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;
+    this.backgroundFrequencies = hmm.getBackgroundFrequencies();
+    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];
+
+    int lastResNo = start - 1;
+    int seqOffset = -1;
+    int gapCount = 0;
+
+
+    for (int seqN = 0; seqN < start; seqN++)
+    {
+      sequence[seqN] = GAP_DASH;
+      seqOffset++;
+    }
+    
+    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++] = GAP_DASH;
+        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;
+  }
+
+  public void setBackgroundFrequencies(Map<Character, Float> bkgdFreqs)
+  {
+    backgroundFrequencies = bkgdFreqs;
+  }
+
+  public void setBackgroundFrequencies(ResidueCount bkgdFreqs)
+  {
+    backgroundFrequencies = new HashMap<>();
+
+    int total = bkgdFreqs.getTotalResidueCount();
+
+    for (char c : bkgdFreqs.getSymbolCounts().symbols)
+    {
+      backgroundFrequencies.put(c, bkgdFreqs.getCount(c) * 1f / total);
+    }
+
+  }
+
+  public Map<Character, Float> getBackgroundFrequencies()
+  {
+    return backgroundFrequencies;
+  }
+
+}
+
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 247f5e5..9ba768d 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;
@@ -59,6 +60,10 @@ public class Sequence extends ASequence implements SequenceI
 
   int end;
 
+  HiddenMarkovModel hmm;
+
+  boolean isHMMConsensusSequence = false;
+
   Vector<PDBEntry> pdbIds;
 
   String vamsasId;
@@ -335,6 +340,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
@@ -1774,7 +1784,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);
@@ -1872,6 +1883,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}
    */
@@ -2045,4 +2084,10 @@ public class Sequence extends ASequence implements SequenceI
     // otherwise, sequence was completely hidden
     return 0;
   }
+
+  @Override
+  public boolean hasHMMProfile()
+  {
+    return hmm != null;
+  }
 }
index e2bb5a6..aa15d1f 100644 (file)
@@ -83,4 +83,12 @@ public interface SequenceCollectionI
    * @return
    */
   boolean isNucleotide();
+
+  /**
+   * Returns the (possibly empty) list of HMM consensus sequences in the
+   * collection
+   * 
+   * @return
+   */
+  List<SequenceI> getHmmSequences();
 }
index 3bf7bc4..59cb4bb 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,11 +45,10 @@ 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);
 
@@ -65,40 +66,46 @@ public class SequenceGroup implements AnnotatedCollectionI
   String groupName;
 
   String description;
-
+  
   Conservation conserve;
 
+  Conservation conservationData;
+
+  ProfilesI consensusProfiles;
+
+  ProfilesI hmmProfiles;
+
   boolean displayBoxes = true;
 
   boolean displayText = true;
 
   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;
 
-  /**
+  /*
    * after Olivier's non-conserved only character display
    */
   boolean showNonconserved = false;
 
-  /**
-   * group members
+  /*
+   * sequences in the group
    */
   private List<SequenceI> sequences;
 
-  /**
+  /*
    * representative sequence for this group (if any)
    */
   private SequenceI seqrep = null;
 
   int width = -1;
 
-  /**
-   * Colourscheme applied to group if any
+  /*
+   * colour scheme applied to group if any
    */
   public ResidueShaderI cs;
 
@@ -122,22 +129,29 @@ public class SequenceGroup implements AnnotatedCollectionI
 
   public Color textColour2 = Color.white;
 
-  /**
-   * consensus calculation property
+  /*
+   * properties for consensus annotation
    */
   private boolean ignoreGapsInConsensus = true;
 
-  /**
-   * consensus calculation property
-   */
   private boolean showSequenceLogo = false;
 
-  /**
-   * flag indicating if logo should be rendered normalised
-   */
   private boolean normaliseSequenceLogo;
 
   /*
+   * 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;
@@ -145,18 +159,22 @@ public class SequenceGroup implements AnnotatedCollectionI
   /*
    * visibility of columns intersecting this group
    */
-  private boolean hidecols = false;
+  private boolean hidecols;
 
   AlignmentAnnotation consensus = null;
 
   AlignmentAnnotation conservation = null;
 
+  private AlignmentAnnotation hmmInformation;
+  
   private boolean showConsensusHistogram;
-
+  
   private AnnotatedCollectionI context;
 
+
   /**
-   * Creates a new SequenceGroup object.
+   * Constructor, assigning a generated default name of "JGroup:" with object
+   * hashcode appended
    */
   public SequenceGroup()
   {
@@ -199,10 +217,13 @@ public class SequenceGroup implements AnnotatedCollectionI
    * copy constructor
    * 
    * @param seqsel
+   * @param keepsequences
+   *          if false do not add sequences from seqsel to new instance
    */
   public SequenceGroup(SequenceGroup seqsel)
   {
     this();
+
     if (seqsel != null)
     {
       sequences = new ArrayList<>();
@@ -228,6 +249,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;
@@ -236,8 +260,12 @@ public class SequenceGroup implements AnnotatedCollectionI
       thresholdTextColour = seqsel.thresholdTextColour;
       width = seqsel.width;
       ignoreGapsInConsensus = seqsel.ignoreGapsInConsensus;
+      hmmIgnoreBelowBackground = seqsel.hmmIgnoreBelowBackground;
+      hmmUseInfoLetterHeight = seqsel.hmmUseInfoLetterHeight;
       if (seqsel.conserve != null)
       {
+        // todo avoid doing this if we don't actually want derived calculations
+        // !
         recalcConservation(); // safer than
         // aaFrequency = (Vector) seqsel.aaFrequency.clone(); // ??
       }
@@ -581,8 +609,9 @@ public class SequenceGroup implements AnnotatedCollectionI
   }
 
   /**
-   * 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
@@ -590,7 +619,8 @@ public class SequenceGroup implements AnnotatedCollectionI
    */
   public boolean recalcConservation(boolean defer)
   {
-    if (cs == null && consensus == null && conservation == null)
+    if (cs == null && consensus == null && conservation == null
+            && hmmInformation == null)
     {
       return false;
     }
@@ -601,6 +631,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());
@@ -701,6 +741,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
@@ -1157,6 +1224,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
    * 
@@ -1243,6 +1326,26 @@ public class SequenceGroup implements AnnotatedCollectionI
     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
@@ -1486,4 +1589,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 15b61d2..d06adcb 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
    */
@@ -501,6 +505,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
@@ -537,7 +547,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
@@ -567,7 +577,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
@@ -577,5 +587,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 fcb6572..67345cd 100644 (file)
@@ -64,6 +64,13 @@ 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.hmmer.JackHMMER;
 import jalview.io.AlignmentProperties;
 import jalview.io.AnnotationFile;
 import jalview.io.BackupFiles;
@@ -98,6 +105,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;
@@ -127,23 +137,26 @@ 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;
 import java.util.Arrays;
 import java.util.Deque;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.Vector;
 
 import javax.swing.ButtonGroup;
 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;
 
@@ -156,7 +169,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;
@@ -182,6 +194,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
    */
   String fileName = null;
 
+
   /**
    * Creates a new AlignFrame object with specific width and height.
    * 
@@ -766,6 +779,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       ap.av.updateConservation(ap);
       ap.av.updateConsensus(ap);
       ap.av.updateStrucConsensus(ap);
+      ap.av.initInformationWorker(ap);
     }
   }
 
@@ -908,6 +922,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());
@@ -1004,6 +1021,258 @@ 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();
+  }
+  
+  @Override
+  public void jackhmmer_actionPerformed(boolean withDefaults)
+  {
+    
+    /*
+     * get default parameters, and (if requested) show 
+     * dialog to allow modification
+     */
+    
+    ParamDatastoreI store = HMMERParamStore.forJackhmmer(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 JackHMMER(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;
+  }
+  
+  @Override
+  protected void filterByEValue_actionPerformed()
+  {
+    viewport.filterByEvalue(inputDouble("Enter E-Value Cutoff"));
+  }
+  
+  @Override
+  protected void filterByScore_actionPerformed()
+  {
+    viewport.filterByScore(inputDouble("Enter Bit Score Threshold"));
+  }
+  
+  private double inputDouble(String message)
+  {
+    String str = null;
+    Double d = null;
+    while(d == null || d <= 0)
+    {
+      str = JOptionPane.showInputDialog(this.alignPanel, message);
+      try
+      {
+        d = Double.valueOf(str);
+      }
+      catch (NumberFormatException e)
+      {
+      }
+    }
+    return d;
+  }
+
+  /**
+   * Checks if the alignment contains the required number of sequences.
+   * 
+   * @param required
+   * @return
+   */
+  public boolean alignmentIsSufficient(int required)
+  {
+      if (getViewport().getSequenceSelection().length < required)
+      {
+        JOptionPane.showMessageDialog(this,
+                MessageManager.getString("label.not_enough_sequences"));
+        return false;
+      }
+      return true;
+  }
+
+  /**
+   * Opens a file browser and adds the selected file, if in Fasta, Stockholm or
+   * Pfam format, to the list held under preference key "HMMSEARCH_DBS" (as a
+   * comma-separated list)
+   */
+  @Override
+  public void addDatabase_actionPerformed() throws IOException
+  {
+    if (Cache.getProperty(Preferences.HMMSEARCH_DBS) == null)
+    {
+      Cache.setProperty(Preferences.HMMSEARCH_DBS, "");
+    }
+
+    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 currentDbPaths = Cache
+                .getProperty(Preferences.HMMSEARCH_DBS);
+        currentDbPaths += Preferences.COMMA + path;
+        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)
@@ -1422,6 +1691,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(
@@ -1907,9 +2177,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);
   }
@@ -1919,9 +2192,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);
   }
@@ -1931,8 +2207,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
@@ -2260,7 +2538,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       System.out.println("Exception whilst pasting: " + ex);
       // could be anything being pasted in here
     }
-
   }
 
   @Override
@@ -3510,6 +3787,28 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     alignPanel.paintAlignment(true, false);
   }
 
+  @Override
+  public void sortEValueMenuItem_actionPerformed(ActionEvent e)
+  {
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
+    AlignmentSorter.sortByEValue(viewport.getAlignment());
+    addHistoryItem(new OrderCommand("Group Sort", oldOrder,
+            viewport.getAlignment()));
+    alignPanel.paintAlignment(true, false);
+
+  }
+
+  @Override
+  public void sortBitScoreMenuItem_actionPerformed(ActionEvent e)
+  {
+    SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
+    AlignmentSorter.sortByBitScore(viewport.getAlignment());
+    addHistoryItem(new OrderCommand("Group Sort", oldOrder,
+            viewport.getAlignment()));
+    alignPanel.paintAlignment(true, false);
+
+  }
+  
   /**
    * DOCUMENT ME!
    * 
@@ -3719,35 +4018,33 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
 
     if (viewport.getAlignment().getAlignmentAnnotation()
-            .hashCode() != _annotationScoreVectorHash)
+            .hashCode() == _annotationScoreVectorHash)
+    {
+      return;
+    }
+
+    sortByAnnotScore.removeAll();
+    Set<String> scoreSorts = new HashSet<>();
+    for (SequenceI sqa : viewport.getAlignment().getSequences())
     {
-      sortByAnnotScore.removeAll();
-      // almost certainly a quicker way to do this - but we keep it simple
-      Hashtable scoreSorts = new Hashtable();
-      AlignmentAnnotation aann[];
-      for (SequenceI sqa : viewport.getAlignment().getSequences())
+      AlignmentAnnotation[] anns = sqa.getAnnotation();
+      for (int i = 0; anns != null && i < anns.length; i++)
       {
-        aann = sqa.getAnnotation();
-        for (int i = 0; aann != null && i < aann.length; i++)
+        AlignmentAnnotation aa = anns[i];
+        if (aa != null && aa.hasScore() && aa.sequenceRef != null)
         {
-          if (aann[i].hasScore() && aann[i].sequenceRef != null)
-          {
-            scoreSorts.put(aann[i].label, aann[i].label);
-          }
+          scoreSorts.add(aa.label);
         }
       }
-      Enumeration labels = scoreSorts.keys();
-      while (labels.hasMoreElements())
-      {
-        addSortByAnnotScoreMenuItem(sortByAnnotScore,
-                (String) labels.nextElement());
-      }
-      sortByAnnotScore.setVisible(scoreSorts.size() > 0);
-      scoreSorts.clear();
-
-      _annotationScoreVectorHash = viewport.getAlignment()
-              .getAlignmentAnnotation().hashCode();
     }
+    for (String label : scoreSorts)
+    {
+      addSortByAnnotScoreMenuItem(sortByAnnotScore, label);
+    }
+    sortByAnnotScore.setVisible(!scoreSorts.isEmpty());
+
+    _annotationScoreVectorHash = viewport.getAlignment()
+            .getAlignmentAnnotation().hashCode();
   }
 
   /**
@@ -4126,7 +4423,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                       jws2servs.attachWSMenuEntry(webService, me);
                       for (Jws2Instance sv : jws2servs.getServices())
                       {
-                        if (sv.description.toLowerCase().contains("jpred"))
+                        if (sv.getName().toLowerCase().contains("jpred"))
                         {
                           for (JMenuItem jmi : legacyItems)
                           {
@@ -4146,6 +4443,10 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
                   }
                 }
                 build_urlServiceMenu(me.webService);
+
+                // TODO Mateusz - follow pattern for adding web service
+                // JMenuItems for slivka-based services
+
                 build_fetchdbmenu(webService);
                 for (JMenu item : wsmenu)
                 {
@@ -4588,6 +4889,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)
@@ -4694,7 +4997,6 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       }
       if (isAnnotation)
       {
-
         alignPanel.adjustAnnotationHeight();
         viewport.updateSequenceIdColours();
         buildSortByAnnotationScoresMenu();
@@ -5638,6 +5940,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
     }
   }
 
+  /**
+   * Sets the status of the HMMER menu
+   */
+  public void updateHMMERStatus()
+  {
+    hmmerMenu.setEnabled(HmmerCommand.isHmmerAvailable());
+  }
+
   @Override
   protected void loadVcf_actionPerformed()
   {
index 61b0d1b..d6e2ae5 100644 (file)
@@ -256,14 +256,13 @@ public class AlignViewport extends AlignmentViewport
 
     setFont(new Font(fontName, style, Integer.parseInt(fontSize)), true);
 
-    alignment
-            .setGapCharacter(Cache.getDefault("GAP_SYMBOL", "-").charAt(0));
+               alignment.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 (hconsensus == null && !isDataset)
     {
-      if (!alignment.isNucleotide())
+                       if (!alignment.isNucleotide())
       {
         showConservation = Cache.getDefault("SHOW_CONSERVATION", true);
         showQuality = Cache.getDefault("SHOW_QUALITY", true);
@@ -275,13 +274,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 = alignment.isNucleotide()
             ? Preferences.DEFAULT_COLOUR_NUC
             : Preferences.DEFAULT_COLOUR_PROT;
     String schemeName = Cache.getProperty(colourProperty);
@@ -304,11 +309,11 @@ public class AlignViewport extends AlignmentViewport
 
     if (residueShading != null)
     {
-      residueShading.setConsensus(hconsensus);
+                       residueShading.setConsensus(hconsensus);
     }
     setColourAppliesToAllGroups(true);
   }
-
+  
   boolean validCharWidth;
 
   /**
@@ -393,7 +398,7 @@ public class AlignViewport extends AlignmentViewport
     /*
      * replace mappings on our alignment
      */
-    if (alignment != null && align != null)
+               if (alignment != null && align != null)
     {
       alignment.setCodonFrames(align.getCodonFrames());
     }
@@ -446,7 +451,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
@@ -466,8 +471,9 @@ public class AlignViewport extends AlignmentViewport
     {
       end = alignment.getWidth();
     }
-    return (alignment.getHiddenColumns().getVisContigsIterator(start, end,
-            false));
+
+    return (alignment.getHiddenColumns().getVisContigsIterator(start,
+            end, false));
   }
 
   /**
@@ -517,7 +523,7 @@ public class AlignViewport extends AlignmentViewport
   }
 
   public boolean followSelection = true;
-
+  
   /**
    * @return true if view selection should always follow the selections
    *         broadcast by other selection sources
@@ -582,18 +588,20 @@ public class AlignViewport extends AlignmentViewport
     return StructureSelectionManager
             .getStructureSelectionManager(Desktop.instance);
   }
-
+  
   @Override
   public boolean isNormaliseSequenceLogo()
   {
     return normaliseSequenceLogo;
   }
 
-  public void setNormaliseSequenceLogo(boolean state)
+  @Override
+public void setNormaliseSequenceLogo(boolean state)
   {
     normaliseSequenceLogo = state;
   }
 
+
   /**
    * 
    * @return true if alignment characters should be displayed
@@ -603,7 +611,7 @@ public class AlignViewport extends AlignmentViewport
   {
     return validCharWidth;
   }
-
+  
   private Hashtable<String, AutoCalcSetting> calcIdParams = new Hashtable<>();
 
   public AutoCalcSetting getCalcIdSettingsFor(String calcId)
index 6da6cc3..bf3ecf2 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;
@@ -352,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);
@@ -399,7 +404,8 @@ public class AnnotationLabels extends JPanel
     if (selectedRow < aa.length)
     {
       final String label = aa[selectedRow].label;
-      if (!aa[selectedRow].autoCalculated)
+      if (!(aa[selectedRow].autoCalculated)
+              && !(InformationThread.HMM_CALC_ID.equals(ann.getCalcId())))
       {
         if (aa[selectedRow].graph == AlignmentAnnotation.NO_GRAPH)
         {
@@ -407,7 +413,7 @@ public class AnnotationLabels extends JPanel
           pop.addSeparator();
           // av and sequencegroup need to implement same interface for
           item = new JCheckBoxMenuItem(TOGGLE_LABELSCALE,
-                  aa[selectedRow].scaleColLabel);
+                         aa[selectedRow].scaleColLabel);
           item.addActionListener(this);
           pop.add(item);
         }
@@ -420,11 +426,169 @@ public class AnnotationLabels extends JPanel
         consclipbrd.addActionListener(this);
         pop.add(consclipbrd);
       }
+      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)
+        {
+          if (!ann.groupRef.isUseInfoLetterHeight())
+          {
+            ann.groupRef.setIgnoreBelowBackground(cbmi.getState());
+            // todo and recompute group annotation
+          }
+        }
+        else if (!ap.av.isInfoLetterHeight())
+        {
+          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);
+    }
+  }
+
+  /**
    * A helper method that adds menu options for calculation and visualisation of
    * group and/or alignment consensus annotation to a popup menu. This is
    * designed to be reusable for either unwrapped mode (popup menu is shown on
@@ -925,7 +1089,6 @@ public class AnnotationLabels extends JPanel
             PaintRefresher.Refresh(ap, ap.av.getSequenceSetId());
             ap.av.sendSelection();
           }
-
         }
       }
       return;
@@ -997,7 +1160,6 @@ public class AnnotationLabels extends JPanel
   @Override
   public void paintComponent(Graphics g)
   {
-
     int width = getWidth();
     if (width == 0)
     {
@@ -1012,7 +1174,6 @@ public class AnnotationLabels extends JPanel
     }
 
     drawComponent(g2, true, width);
-
   }
 
   /**
index 336a312..9abef1f 100644 (file)
@@ -23,11 +23,13 @@ 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.bin.Cache;
 import jalview.datamodel.SequenceGroup;
 import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -537,7 +539,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)
     {
@@ -564,7 +566,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 1ec6939..15752ba 100644 (file)
@@ -1499,7 +1499,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 d6090e2..7850ff3 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..5b411b4 100644 (file)
  */
 package jalview.gui;
 
+import jalview.bin.Cache;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
+import jalview.io.JalviewFileChooser;
+import jalview.io.JalviewFileView;
 import jalview.util.MessageManager;
+import jalview.ws.jws2.dm.JabaOption;
 import jalview.ws.params.ArgumentI;
 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.FileParameter;
+import jalview.ws.params.simple.LogarithmicParameter;
+import jalview.ws.params.simple.RadioChoiceParameter;
+import jalview.ws.params.simple.StringParameter;
 
 import java.awt.BorderLayout;
+import java.awt.Color;
 import java.awt.Component;
+import java.awt.Container;
 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.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
+import java.io.File;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.swing.ButtonGroup;
 import javax.swing.JButton;
 import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
@@ -52,6 +68,7 @@ import javax.swing.JLabel;
 import javax.swing.JMenuItem;
 import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
+import javax.swing.JRadioButton;
 import javax.swing.JScrollPane;
 import javax.swing.JSlider;
 import javax.swing.JTextArea;
@@ -71,15 +88,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,57 +126,89 @@ public class OptsAndParamsPage
 
     OptionI option;
 
-    JLabel optlabel = new JLabel();
-
-    JComboBox val = new JComboBox();
+    JComboBox<Object> val;
 
+    /**
+     * Constructs and adds labels and controls to the panel for one Option
+     * 
+     * @param opt
+     */
     public OptionBox(OptionI opt)
     {
       option = opt;
-      setLayout(new BorderLayout());
-      enabled.setSelected(opt.isRequired()); // TODO: lock required options
+      setLayout(new FlowLayout(FlowLayout.LEFT));
+      enabled = new JCheckBox(opt.getName());
+      enabled.setSelected(opt.isRequired());
+
+      /*
+       * If option is required, show a label, if optional a checkbox
+       * (but not for Jabaws pending JWS-126 resolution)
+       */
+      if (opt.isRequired() && !(opt instanceof JabaOption))
+      {
+        finfo = null;
+        add(new JLabel(opt.getName()));
+      }
+      else
+      {
+        finfo = option.getFurtherDetails();
+        configureCheckbox(opt);
+        add(enabled);
+      }
+
+      /*
+       * construct the choice box with possible values, 
+       * or their display names if provided
+       */
+      val = buildComboBox(opt);
+      val.setSelectedItem(opt.getValue());
+
+      /*
+       * only show the choicebox if there is more than one option,
+       * or the option is mandatory
+       */
+      if (opt.getPossibleValues().size() > 1 || opt.isRequired())
+      {
+        val.addActionListener(this);
+        add(val);
+      }
+
+      setInitialValue();
+    }
+
+    /**
+     * Configures the checkbox that controls whether or not the option is
+     * selected
+     * 
+     * @param opt
+     */
+    protected void configureCheckbox(OptionI opt)
+    {
       enabled.setFont(new Font("Verdana", Font.PLAIN, 11));
-      enabled.setText("");
-      enabled.setText(opt.getName());
       enabled.addActionListener(this);
-      finfo = option.getFurtherDetails();
-      String desc = opt.getDescription();
+      final String desc = opt.getDescription();
       if (finfo != null)
       {
         hasLink = true;
-
-        enabled.setToolTipText(JvSwingUtils.wrapTooltip(true,
-                ((desc == null || desc.trim().length() == 0)
-                        ? MessageManager.getString(
-                                "label.opt_and_params_further_details")
-                        : desc) + "<br><img src=\"" + linkImageURL
-                        + "\"/>"));
-        enabled.addMouseListener(this);
+        String description = desc;
+        if (desc == null || desc.trim().isEmpty())
+        {
+          description = MessageManager
+                  .getString("label.opt_and_params_further_details");
+        }
+        description = description + "<br><img src=\"" + linkImageURL
+                + "\"/>";
+        String text = JvSwingUtils.wrapTooltip(true, description);
+        enabled.setToolTipText(text);
+        enabled.addMouseListener(this); // for popup menu to show link
       }
       else
       {
         if (desc != null && desc.trim().length() > 0)
         {
-          enabled.setToolTipText(
-                  JvSwingUtils.wrapTooltip(true, opt.getDescription()));
+          enabled.setToolTipText(JvSwingUtils.wrapTooltip(true, desc));
         }
       }
-      add(enabled, BorderLayout.NORTH);
-      for (Object str : opt.getPossibleValues())
-      {
-        val.addItem(str);
-      }
-      val.setSelectedItem(opt.getValue());
-      if (opt.getPossibleValues().size() > 1)
-      {
-        setLayout(new GridLayout(1, 2));
-        val.addActionListener(this);
-        add(val, BorderLayout.SOUTH);
-      }
-      // TODO: add actionListeners for popup (to open further info),
-      // and to update list of parameters if an option is enabled
-      // that takes a value. JBPNote: is this TODO still valid ?
-      setInitialValue();
     }
 
     @Override
@@ -178,31 +245,21 @@ public class OptsAndParamsPage
       poparent.argSetModified(this, !notmod);
     }
 
-    public OptionI getOptionIfEnabled()
+    /**
+     * Answers null if the option is not selected, else a new Option holding the
+     * selected value
+     * 
+     * @return
+     */
+    public ArgumentI getSelectedOption()
     {
       if (!enabled.isSelected())
       {
         return null;
       }
+      String value = getSelectedValue(option, val.getSelectedIndex());
       OptionI opt = option.copy();
-      if (opt.getPossibleValues() != null
-              && opt.getPossibleValues().size() == 1)
-      {
-        // Hack to make sure the default value for an enabled option with only
-        // one value is actually returned
-        opt.setValue(opt.getPossibleValues().get(0));
-      }
-      if (val.getSelectedItem() != null)
-      {
-        opt.setValue((String) val.getSelectedItem());
-      }
-      else
-      {
-        if (option.getValue() != null)
-        {
-          opt.setValue(option.getValue());
-        }
-      }
+      opt.setValue(value);
       return opt;
     }
 
@@ -218,15 +275,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 +321,57 @@ 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 choice = false;
+    boolean isIntegerParameter;
 
-    JComboBox choicebox;
+    boolean isStringParameter;
 
-    JPanel controlPanel = new JPanel();
+    boolean adjusting;
 
-    boolean descisvisible = false;
+    /*
+     * drop-down list of choice options (if applicable)
+     */
+    JComboBox<Object> choicebox;
+
+    /*
+     * radio buttons as an alternative to combo box
+     */
+    ButtonGroup buttonGroup;
+
+    JPanel controlsPanel = new JPanel();
+
+    boolean descriptionIsVisible = false;
 
     JScrollPane descPanel = new JScrollPane();
 
     final URL finfo;
 
-    boolean integ = false;
-
     Object lastVal;
 
     ParameterI parameter;
@@ -297,58 +380,82 @@ 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
+                || type == ValueType.File;
+
+        /*
+         * 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 +464,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 +524,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 +582,22 @@ public class OptsAndParamsPage
       {
         return;
       }
-      if (!choice)
-      {
-        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())
+      Object newValue = updateSliderFromValueField();
+      boolean modified = true;
+      if (newValue.getClass() == lastVal.getClass())
       {
-        if (cstate instanceof int[])
-        {
-          notmod = (((int[]) cstate)[0] == ((int[]) lastVal)[0]);
-        }
-        else if (cstate instanceof float[])
-        {
-          notmod = (((float[]) cstate)[0] == ((float[]) lastVal)[0]);
-        }
-        else if (cstate instanceof String[])
-        {
-          notmod = (((String[]) cstate)[0].equals(((String[]) lastVal)[0]));
-        }
+        modified = !newValue.equals(lastVal);
       }
-      pmdialogbox.argSetModified(this, !notmod);
+      pmdialogbox.argSetModified(this, modified);
     }
 
     @Override
@@ -502,22 +615,30 @@ public class OptsAndParamsPage
       return Component.BaselineResizeBehavior.CONSTANT_ASCENT;
     }
 
-    public int getBoxHeight()
-    {
-      return (descisvisible ? PARAM_HEIGHT : PARAM_CLOSEDHEIGHT);
-    }
-
-    public ParameterI getParameter()
+    /**
+     * Answers an argument holding the value entered or selected in the dialog
+     * 
+     * @return
+     */
+    public ArgumentI getParameter()
     {
       ParameterI prm = parameter.copy();
-      if (choice)
+      String value = null;
+      if (parameter instanceof RadioChoiceParameter)
+      {
+        value = buttonGroup.getSelection().getActionCommand();
+      }
+      else if (isChoiceParameter)
       {
-        prm.setValue((String) choicebox.getSelectedItem());
+        value = getSelectedValue(this.parameter,
+                choicebox.getSelectedIndex());
       }
       else
       {
-        prm.setValue(valueField.getText());
+        value = valueField.getText();
       }
+      prm.setValue(value);
+
       return prm;
     }
 
@@ -539,15 +660,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 +679,98 @@ 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);
+    }
+
+    /**
+     * 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());
     }
 
-    public void updateControls(ParameterI parm)
+    void updateControls(ParameterI parm)
     {
       adjusting = true;
-      boolean init = (choicebox == null && valueField == null);
+      boolean init = (choicebox == null && valueField == null
+              && buttonGroup == null);
       if (init)
       {
-        if (choice)
+        if (parm instanceof RadioChoiceParameter)
         {
-          choicebox = new JComboBox();
+          buttonGroup = addRadioButtons(parameter, controlsPanel);
+        }
+        else if (isChoiceParameter)
+        {
+          choicebox = buildComboBox(parm);
           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,161 +778,245 @@ 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));
+          if (parm instanceof FileParameter)
+          {
+            valueField.setToolTipText(MessageManager
+                    .getString("label.double_click_to_browse"));
+            valueField.addMouseListener(new MouseAdapter()
+            {
+              @Override
+              public void mouseClicked(MouseEvent e)
+              {
+                if (e.getClickCount() == 2)
+                {
+                  String dir = Cache.getProperty("LAST_DIRECTORY");
+                  JalviewFileChooser chooser = new JalviewFileChooser(dir);
+                  chooser.setFileView(new JalviewFileView());
+                  chooser.setDialogTitle(
+                          MessageManager.getString("action.select_ddbb"));
+
+                  int val = chooser.showOpenDialog(ParamBox.this);
+                  if (val == JalviewFileChooser.APPROVE_OPTION)
+                  {
+                    File choice = chooser.getSelectedFile();
+                    String path = choice.getPath();
+                    valueField.setText(path);
+                    Cache.setProperty("LAST_DIRECTORY", choice.getParent());
+                    FileLoader.updateRecentlyOpened(path,
+                            DataSourceType.FILE);
+                  }
+                }
+              }
+            });
+          }
+          
+          controlsPanel.add(slider, BorderLayout.WEST);
+          controlsPanel.add(valueField, BorderLayout.EAST);
         }
       }
 
-      if (parm != null)
+      String value = parm.getValue();
+      if (value != null)
       {
-        if (choice)
+        if (isChoiceParameter)
         {
-          if (init)
-          {
-            List vals = parm.getPossibleValues();
-            for (Object val : vals)
-            {
-              choicebox.addItem(val);
-            }
-          }
-
-          if (parm.getValue() != null)
+          if (!(parm instanceof RadioChoiceParameter))
           {
-            choicebox.setSelectedItem(parm.getValue());
+            choicebox.setSelectedItem(value);
           }
         }
         else
         {
-          valueField.setText(parm.getValue());
+          valueField.setText(value);
         }
       }
       lastVal = updateSliderFromValueField();
       adjusting = false;
     }
 
-    public Object updateSliderFromValueField()
+    /**
+     * Adds a panel to comp, containing a label and radio buttons for the choice
+     * of values of the given option. Returns a ButtonGroup whose members are
+     * the added radio buttons.
+     * 
+     * @param option
+     * @param comp
+     * 
+     * @return
+     */
+    protected ButtonGroup addRadioButtons(OptionI option, Container comp)
     {
-      int iVal;
-      float fVal;
-      if (validator != null)
+      ButtonGroup bg = new ButtonGroup();
+      JPanel radioPanel = new JPanel();
+      radioPanel.add(new JLabel(option.getDescription()));
+
+      String value = option.getValue();
+
+      for (String opt : option.getPossibleValues())
+      {
+        JRadioButton btn = new JRadioButton(opt);
+        btn.setActionCommand(opt);
+        boolean selected = opt.equals(value);
+        btn.setSelected(selected);
+        btn.addActionListener(this);
+        bg.add(btn);
+        radioPanel.add(btn);
+      }
+      comp.add(radioPanel);
+
+      return bg;
+    }
+
+    /**
+     * 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 or radio button, 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()
+    {
+      if (validator == null || isStringParameter)
       {
-        if (integ)
+        if (isChoiceParameter)
         {
-          iVal = 0;
-          try
+          if (parameter instanceof RadioChoiceParameter)
           {
-            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);
+            return buttonGroup.getSelection().getActionCommand();
           }
           else
           {
-            slider.setVisible(false);
+            return getSelectedValue(this.parameter,
+                    choicebox.getSelectedIndex());
           }
-          return new int[] { iVal };
         }
-        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 +1046,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 +1066,6 @@ public class OptsAndParamsPage
     this.paramSet = paramSet;
   }
 
-  OptsParametersContainerI poparent;
-
   OptionBox addOption(OptionI opt)
   {
     OptionBox cb = optSet.get(opt.getName());
@@ -870,11 +1109,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())
     {
@@ -898,16 +1135,18 @@ public class OptsAndParamsPage
   }
 
   /**
-   * recover options and parameters from GUI
+   * Answers a list of arguments representing all the options and arguments
+   * selected on the dialog, holding their chosen or input values. Optional
+   * parameters which were not selected are not included.
    * 
    * @return
    */
   public List<ArgumentI> getCurrentSettings()
   {
-    List<ArgumentI> argSet = new ArrayList<ArgumentI>();
+    List<ArgumentI> argSet = new ArrayList<>();
     for (OptionBox opts : getOptSet().values())
     {
-      OptionI opt = opts.getOptionIfEnabled();
+      ArgumentI opt = opts.getSelectedOption();
       if (opt != null)
       {
         argSet.add(opt);
@@ -915,7 +1154,7 @@ public class OptsAndParamsPage
     }
     for (ParamBox parambox : getParamSet().values())
     {
-      ParameterI parm = parambox.getParameter();
+      ArgumentI parm = parambox.getParameter();
       if (parm != null)
       {
         argSet.add(parm);
@@ -925,4 +1164,57 @@ public class OptsAndParamsPage
     return argSet;
   }
 
+  /**
+   * A helper method that constructs and returns a CombBox for choice of the
+   * possible option values. If display names are provided, then these are added
+   * as options, otherwise the actual values are added.
+   * 
+   * @param opt
+   * @return
+   */
+  protected static JComboBox<Object> buildComboBox(OptionI opt)
+  {
+    JComboBox<Object> cb = null;
+    List<String> displayNames = opt.getDisplayNames();
+    if (displayNames != null)
+    {
+      List<Object> displayNamesObjects = new ArrayList<>();
+      displayNamesObjects.addAll(displayNames);
+      cb = JvSwingUtils.buildComboWithTooltips(displayNamesObjects,
+              opt.getPossibleValues());
+    }
+    else
+    {
+      cb = new JComboBox<>();
+      for (String v : opt.getPossibleValues())
+      {
+        cb.addItem(v);
+      }
+    }
+    return cb;
+  }
+
+  /**
+   * Answers the value corresponding to the selected item in the choice combo
+   * box. Note that this returns the underlying value even if a different
+   * display name is used in the combo box.
+   * 
+   * @return
+   */
+  protected static String getSelectedValue(OptionI opt, int sel)
+  {
+    List<String> possibleValues = opt.getPossibleValues();
+    String value = null;
+    if (possibleValues != null && possibleValues.size() == 1)
+    {
+      // Hack to make sure the default value for an enabled option with only
+      // one value is actually returned even if this.val is not displayed
+      value = possibleValues.get(0);
+    }
+    else if (sel >= 0 && sel < possibleValues.size())
+    {
+      value = possibleValues.get(sel);
+    }
+    return value;
+  }
 }
index 9d0a55d..4e304c2 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 415054e..2034b3f 100644 (file)
@@ -35,10 +35,12 @@ import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.MappedFeatures;
 import jalview.datamodel.PDBEntry;
+import jalview.datamodel.ResidueCount;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.gui.ColourMenuHelper.ColourChangeListener;
+import jalview.io.CountReader;
 import jalview.io.FileFormatI;
 import jalview.io.FileFormats;
 import jalview.io.FormatAdapter;
@@ -59,6 +61,8 @@ import jalview.viewmodel.seqfeatures.FeatureRendererModel;
 import java.awt.Color;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.net.MalformedURLException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.BitSet;
@@ -534,6 +538,36 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
         }
       }
 
+      if (seq.hasHMMProfile())
+      {
+        menuItem = new JMenuItem(MessageManager
+                .getString("action.add_background_frequencies"));
+        menuItem.addActionListener(new ActionListener()
+        {
+          @Override
+          public void actionPerformed(ActionEvent e)
+          {
+            try
+            {
+              ResidueCount counts = CountReader.getBackgroundFrequencies(ap,
+                      seq);
+              if (counts != null)
+              {
+                seq.getHMM().setBackgroundFrequencies(counts);
+                ap.alignFrame.buildColourMenu();
+              }
+            } catch (MalformedURLException e1)
+            {
+              e1.printStackTrace();
+            } catch (IOException e1)
+            {
+              e1.printStackTrace();
+            }
+          }
+        });
+        add(menuItem);
+      }
+
       menuItem = new JMenuItem(
               MessageManager.getString("action.hide_sequences"));
       menuItem.addActionListener(new ActionListener()
@@ -658,7 +692,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 9754e0d..a0a7511 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.BackupFiles;
 import jalview.io.BackupFilesPresetEntry;
 import jalview.io.FileFormatI;
@@ -38,6 +39,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;
@@ -50,6 +52,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;
@@ -60,6 +64,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;
@@ -83,6 +88,15 @@ import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
  */
 public class Preferences extends GPreferences
 {
+  // suggested list delimiter character
+  public static final String COMMA = ",";
+
+  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";
@@ -104,6 +118,12 @@ 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_DBS = "HMMSEARCH_DBS";
 
   public static final String SORT_ANNOTATIONS = "SORT_ANNOTATIONS";
 
@@ -205,6 +225,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));
@@ -227,6 +304,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
@@ -614,6 +694,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,
@@ -660,6 +744,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());
@@ -925,6 +1045,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
@@ -1206,6 +1328,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
@@ -1254,6 +1427,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 2e2593b..06f4e06 100644 (file)
@@ -471,10 +471,13 @@ public class RestServiceEditorPane extends GRestServiceEditorPane
             final Thread runner = Thread.currentThread();
             JFrame df = new JFrame();
             df.getContentPane().setLayout(new BorderLayout());
-            df.getContentPane().add((nulserv = !nulserv)
-                    ? new RestServiceEditorPane(jalview.ws.rest.RestClient
-                            .makeShmmrRestClient().getRestDescription())
-                    : new RestServiceEditorPane(), BorderLayout.CENTER);
+            df.getContentPane().add(
+                    (nulserv = !nulserv) ? new RestServiceEditorPane(
+                            jalview.ws.rest.clientdefs.ShmrRestClient
+                                    .makeShmmrRestClient()
+                                    .getRestDescription())
+                            : new RestServiceEditorPane(),
+                    BorderLayout.CENTER);
             df.setBounds(100, 100, 600, 400);
             df.addComponentListener(new ComponentListener()
             {
index 25dedc5..a8a13a4 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;
@@ -216,8 +217,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..f7906e5 100644 (file)
@@ -23,10 +23,7 @@ package jalview.gui;
 import jalview.gui.OptsAndParamsPage.OptionBox;
 import jalview.gui.OptsAndParamsPage.ParamBox;
 import jalview.util.MessageManager;
-import jalview.ws.jws2.JabaParamStore;
-import jalview.ws.jws2.JabaPreset;
-import jalview.ws.jws2.Jws2Discoverer;
-import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.api.UIinfo;
 import jalview.ws.params.ArgumentI;
 import jalview.ws.params.OptionI;
 import jalview.ws.params.ParamDatastoreI;
@@ -48,22 +45,16 @@ import java.awt.event.HierarchyBoundsListener;
 import java.awt.event.HierarchyEvent;
 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;
 import java.util.Vector;
 
 import javax.swing.JButton;
 import javax.swing.JComboBox;
 import javax.swing.JDialog;
-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;
@@ -71,13 +62,6 @@ 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;
-
 /**
  * job parameter editing/browsing dialog box. User can browse existing settings
  * (user + presets + Defaults), and any changes to parameters creates a modified
@@ -96,36 +80,35 @@ 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 int DEFAULT_HEIGHT = 640;
+
+  // the default parameter set shown to the user
+  private static final String SVC_DEF = "Defaults";
 
-  private static final String SVC_DEF = "Defaults"; // this is the null
-                                                    // parameter set as shown to
-                                                    // user
+  private int maxOptWidth = 200;
+
+  // URL linkImageURL = getClass().getResource("/images/link.gif");
+
+  // TODO ABSRACT FROM JABAWS CLASSES
 
   /**
    * manager for options and parameters.
    */
-  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 setDetails = new JPanel();
-
-  JSplitPane settingsPanel = new JSplitPane();
+  JPanel paramsPanel = new JPanel();
 
-  JPanel jobPanel = new JPanel();
-
-  JScrollPane jobOptionsPane = new JScrollPane();
+  JPanel setNamePanel = new JPanel();
 
   JButton createpref = new JButton();
 
@@ -135,81 +118,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);
-  }
+  UIinfo service;
 
-  /**
-   * 
-   * @param desktop
-   *          - if null, create new JFrame outside of desktop
-   * @param service
-   * @param preset
+  /*
+   * list of service presets in the gui
+   */
+  Hashtable<String, String> servicePresets = null;
+
+  /*
+   * set if dialog is being set - so handlers will avoid spurious events
    */
-  public WsJobParameters(JFrame parent, Jws2Instance service,
-          WsParamSetI preset, List<Argument> jobArgset)
+  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, UIinfo service,
+          WsParamSetI preset, List<ArgumentI> 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 +199,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 +228,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 +258,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                update_actionPerformed(e);
+                update_actionPerformed();
               }
             });
     deletepref = JvSwingUtils.makeButton(
@@ -289,7 +270,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                delete_actionPerformed(e);
+                delete_actionPerformed();
               }
             });
     createpref = JvSwingUtils.makeButton(
@@ -301,7 +282,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                create_actionPerformed(e);
+                create_actionPerformed();
               }
             });
     revertpref = JvSwingUtils.makeButton(
@@ -314,10 +295,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 +307,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 +318,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 +341,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 +356,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 +367,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 +381,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 +415,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 +446,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 +457,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,55 +476,40 @@ 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;
+  void initForService(WsParamSetI paramSet, List<ArgumentI> jobArgset)
+  {
+    settingDialog = true;
 
-  /**
-   * list of service presets in the gui
-   */
-  Hashtable servicePresets = null;
+    init(paramSet, jobArgset);
 
-  /**
-   * 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 init(WsParamSetI p, List<ArgumentI> jobArgset)
   {
-    WsParamSetI p = null;
-    List<ArgumentI> jobArgset = null;
-    settingDialog = true;
-    { // instantiate the abstract proxy for Jaba objects
-      jobArgset = jabajobArgset == null ? null
-              : JabaParamStore.getJwsArgsfromJaba(jabajobArgset);
-      p = jabap; // (jabap != null) ? paramStore.getPreset(jabap.getName()) :
-                 // null;
-    }
-
-    Hashtable exnames = new Hashtable();
+    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 +517,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 +558,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 +596,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 +667,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 +731,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     if (b && modifiedElements.size() > 0)
     {
       makeSetNameValid(!isUserPreset);
-      SetNamePanel.revalidate();
+      setNamePanel.revalidate();
     }
     updateButtonDisplay();
   }
@@ -818,7 +778,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 +798,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
-        {
-          jobOptions.add(pbox);
-        }
-        if (fh)
+        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)
         {
-          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)
+        int boxWidth = pbox.getSize().width;
+        currentWidth += boxWidth + hgap;
+        boolean wrapAfterLast = currentWidth > availableWidth
+                && lastAdded != null;
+        if (wrapAfterLast)
         {
-          paramList.add(pbox, "wrap");
-          cw = pbox.getSize().width + hgap;
-          fh = true;
+          paramsPanel.remove(lastAdded);
+          paramsPanel.add(lastAdded, "wrap");
+          currentWidth = pbox.getSize().width + hgap;
         }
-        else
-        {
-          paramList.add(pbox);
-        }
-        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 +891,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
@@ -955,243 +907,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
     revalidate();
   }
 
-  /**
-   * testing method - grab a service and parameter set and show the window
-   * 
-   * @param args
-   */
-  public static void main(String[] args)
-  {
-    jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer
-            .getDiscoverer();
-    int p = 0;
-    if (args.length > 0)
-    {
-      Vector<String> services = new Vector<String>();
-      services.addElement(args[p++]);
-      Jws2Discoverer.getDiscoverer().setServiceUrls(services);
-    }
-    try
-    {
-      disc.run();
-    } catch (Exception e)
-    {
-      System.err.println("Aborting. Problem discovering services.");
-      e.printStackTrace();
-      return;
-    }
-    Jws2Instance lastserv = null;
-    for (Jws2Instance service : disc.getServices())
-    {
-      lastserv = service;
-      if (p >= args.length || service.serviceType.equalsIgnoreCase(args[p]))
-      {
-        if (lastserv != null)
-        {
-          List<Preset> prl = null;
-          Preset pr = null;
-          if (++p < args.length)
-          {
-            PresetManager prman = lastserv.getPresets();
-            if (prman != null)
-            {
-              pr = prman.getPresetByName(args[p]);
-              if (pr == null)
-              {
-                // just grab the last preset.
-                prl = prman.getPresets();
-              }
-            }
-          }
-          else
-          {
-            PresetManager prman = lastserv.getPresets();
-            if (prman != null)
-            {
-              prl = prman.getPresets();
-            }
-          }
-          Iterator<Preset> en = (prl == null) ? null : prl.iterator();
-          while (en != null && en.hasNext())
-          {
-            if (en != null)
-            {
-              if (!en.hasNext())
-              {
-                en = prl.iterator();
-              }
-              pr = en.next();
-            }
-            {
-              System.out.println("Testing opts dupes for "
-                      + lastserv.getUri() + " : " + lastserv.getActionText()
-                      + ":" + pr.getName());
-              List<Option> rg = lastserv.getRunnerConfig().getOptions();
-              for (Option o : rg)
-              {
-                try
-                {
-                  Option cpy = jalview.ws.jws2.ParameterUtils.copyOption(o);
-                } catch (Exception e)
-                {
-                  System.err.println("Failed to copy " + o.getName());
-                  e.printStackTrace();
-                } catch (Error e)
-                {
-                  System.err.println("Failed to copy " + o.getName());
-                  e.printStackTrace();
-                }
-              }
-            }
-            {
-              System.out.println("Testing param dupes:");
-              List<Parameter> rg = lastserv.getRunnerConfig()
-                      .getParameters();
-              for (Parameter o : rg)
-              {
-                try
-                {
-                  Parameter cpy = jalview.ws.jws2.ParameterUtils
-                          .copyParameter(o);
-                } catch (Exception e)
-                {
-                  System.err.println("Failed to copy " + o.getName());
-                  e.printStackTrace();
-                } catch (Error e)
-                {
-                  System.err.println("Failed to copy " + o.getName());
-                  e.printStackTrace();
-                }
-              }
-            }
-            {
-              System.out.println("Testing param write:");
-              List<String> writeparam = null, readparam = null;
-              try
-              {
-                writeparam = jalview.ws.jws2.ParameterUtils
-                        .writeParameterSet(
-                                pr.getArguments(lastserv.getRunnerConfig()),
-                                " ");
-                System.out.println("Testing param read :");
-                List<Option> pset = jalview.ws.jws2.ParameterUtils
-                        .processParameters(writeparam,
-                                lastserv.getRunnerConfig(), " ");
-                readparam = jalview.ws.jws2.ParameterUtils
-                        .writeParameterSet(pset, " ");
-                Iterator<String> o = pr.getOptions().iterator(),
-                        s = writeparam.iterator(), t = readparam.iterator();
-                boolean failed = false;
-                while (s.hasNext() && t.hasNext())
-                {
-                  String on = o.next(), sn = s.next(), st = t.next();
-                  if (!sn.equals(st))
-                  {
-                    System.out.println(
-                            "Original was " + on + " Phase 1 wrote " + sn
-                                    + "\tPhase 2 wrote " + st);
-                    failed = true;
-                  }
-                }
-                if (failed)
-                {
-                  System.out.println(
-                          "Original parameters:\n" + pr.getOptions());
-                  System.out.println(
-                          "Wrote parameters in first set:\n" + writeparam);
-                  System.out.println(
-                          "Wrote parameters in second set:\n" + readparam);
-
-                }
-              } catch (Exception e)
-              {
-                e.printStackTrace();
-              }
-            }
-            WsJobParameters pgui = new WsJobParameters(lastserv,
-                    new JabaPreset(lastserv, pr));
-            JFrame jf = new JFrame(MessageManager
-                    .formatMessage("label.ws_parameters_for", new String[]
-                    { lastserv.getActionText() }));
-            JPanel cont = new JPanel(new BorderLayout());
-            pgui.validate();
-            cont.setPreferredSize(pgui.getPreferredSize());
-            cont.add(pgui, BorderLayout.CENTER);
-            jf.setLayout(new BorderLayout());
-            jf.add(cont, BorderLayout.CENTER);
-            jf.validate();
-            final Thread thr = Thread.currentThread();
-            jf.addWindowListener(new WindowListener()
-            {
-
-              @Override
-              public void windowActivated(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-              @Override
-              public void windowClosed(WindowEvent e)
-              {
-              }
-
-              @Override
-              public void windowClosing(WindowEvent e)
-              {
-                thr.interrupt();
-
-              }
-
-              @Override
-              public void windowDeactivated(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-              @Override
-              public void windowDeiconified(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-              @Override
-              public void windowIconified(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-              @Override
-              public void windowOpened(WindowEvent e)
-              {
-                // TODO Auto-generated method stub
-
-              }
-
-            });
-            jf.setVisible(true);
-            boolean inter = false;
-            while (!inter)
-            {
-              try
-              {
-                Thread.sleep(10000);
-              } catch (Exception e)
-              {
-                inter = true;
-              }
-              ;
-            }
-            jf.dispose();
-          }
-        }
-      }
-    }
-  }
-
   public boolean isServiceDefaults()
   {
     return (!isModified()
@@ -1203,8 +918,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
     return opanp.getCurrentSettings();
   }
 
-  String lastParmSet = null;
-
   /*
    * Hashtable<String, Object[]> editedParams = new Hashtable<String,
    * Object[]>();
@@ -1244,10 +957,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 +1028,7 @@ public class WsJobParameters extends JPanel implements ItemListener,
     initArgSetModified();
     syncSetNamesWithStore();
     setName.setSelectedItem(lastParmSet);
-    SetNamePanel.validate();
+    setNamePanel.validate();
     validate();
     settingDialog = false;
   }
@@ -1326,6 +1039,10 @@ public class WsJobParameters extends JPanel implements ItemListener,
    */
   protected void updateWebServiceMenus()
   {
+    if (Desktop.instance == null)
+    {
+      return;
+    }
     for (AlignFrame alignFrame : Desktop.getAlignFrames())
     {
       alignFrame.BuildWebServiceMenu();
@@ -1337,11 +1054,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
@@ -1397,12 +1115,6 @@ public class WsJobParameters extends JPanel implements ItemListener,
 
   }
 
-  private void _renameExistingPreset(String oldName, String curSetName2)
-  {
-    paramStore.updatePreset(oldName, curSetName2, setDescr.getText(),
-            getJobParams());
-  }
-
   /**
    * store current settings as given name. You should then reset gui.
    * 
index cb98856..43da8dd 100644 (file)
@@ -56,13 +56,14 @@ import javax.xml.stream.XMLStreamReader;
  */
 public class WsParamSetManager implements ParamManager
 {
+  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;
@@ -107,7 +108,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);
       }
     }
@@ -216,7 +218,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)
       {
@@ -226,7 +228,8 @@ public class WsParamSetManager implements ParamManager
         }
         paramFiles = paramFiles.concat(filename);
       }
-      Cache.setProperty("WS_PARAM_FILES", paramFiles);
+
+      Cache.setProperty(WS_PARAM_FILES, paramFiles);
 
       WebServiceParameterSet paramxml = new WebServiceParameterSet();
 
@@ -288,7 +291,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();
@@ -301,7 +304,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..d66ec33
--- /dev/null
@@ -0,0 +1,338 @@
+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";
+
+  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);
+
+    // ensure alignments are the same length
+    alignment.padGaps();
+
+    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, true));
+    args.add(getFilePath(modelFile, true));
+    args.add(getFilePath(alignmentFile, true));
+    
+    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, false),
+            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..0c47c1d
--- /dev/null
@@ -0,0 +1,370 @@
+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.ResidueCount;
+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(viewport.getAlignmentView(false)
+                  .getVisibleAlignment('-'));
+        }
+        else if (MessageManager.getString("label.groups_and_alignment")
+                .equals(value))
+        {
+          runBuildFor.add(viewport.getAlignmentView(false)
+                  .getVisibleAlignment('-'));
+          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)
+        {
+          if (seq != null)
+          {
+            copy.add(seq);
+          }
+        }
+      }
+      // TODO rather than copy alignment data we should anonymize in situ -
+      // export/File import could use anonymization hash to reinstate references
+      // at import level ?
+
+      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();
+      }
+    }
+  }
+
+  /**
+   * 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, true));
+    args.add(getFilePath(sequencesFile, true));
+
+    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();
+
+
+
+    ResidueCount counts = new ResidueCount(alignment.getSequences());
+    hmmSeq.getHMM().setBackgroundFrequencies(counts);
+
+    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..df9ab55
--- /dev/null
@@ -0,0 +1,481 @@
+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.FileParameter;
+import jalview.ws.params.simple.IntegerParameter;
+import jalview.ws.params.simple.LogarithmicParameter;
+import jalview.ws.params.simple.Option;
+import jalview.ws.params.simple.RadioChoiceParameter;
+import jalview.ws.params.simple.StringParameter;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+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 static final String JACKHMMER = "jackhmmer";
+
+  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);
+  }
+
+  public static HMMERParamStore forJackhmmer(AlignmentViewport viewport)
+  {
+    return new HMMERParamStore(JACKHMMER, 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;
+    case JACKHMMER:
+      getJackhmmerParams(args);
+    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'
+     */
+    args.add(new BooleanOption(
+            MessageManager.getString(HMMSearch.AUTO_ALIGN_SEQS_KEY),
+            MessageManager.getString("label.auto_align_seqs_desc"), false,
+            false, false, 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));
+    args.add(new BooleanOption(
+            MessageManager.getString(HMMSearch.RETURN_N_NEW_SEQ),
+            MessageManager.getString("label.check_for_new_sequences_desc"),
+            false, false, false, null));
+
+    /*
+     * 'Parameters'
+     */
+    addChoiceOfHmm(args);
+
+    // addChoiceOfDatabase(args);
+
+    String thisAlignment = MessageManager
+            .getString(HMMSearch.THIS_ALIGNMENT_KEY);
+    String database = MessageManager.getString("label.database");
+    args.add(new FileParameter(database, "", false, "", ""));
+    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 RadioChoiceParameter(
+            MessageManager.getString(HMMSearch.REPORTING_CUTOFF_KEY), null,
+            Arrays.asList(MessageManager.getString(HMMSearch.CUTOFF_EVALUE),
+                    MessageManager.getString(HMMSearch.CUTOFF_SCORE)),
+            MessageManager.getString(HMMSearch.CUTOFF_EVALUE)));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(HMMSearch.REPORTING_SEQ_EVALUE_KEY),
+            MessageManager.getString("label.reporting_seq_e_value_desc"),
+            false, 1D,
+            1E-100, 10D));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(HMMSearch.REPORTING_DOM_EVALUE_KEY),
+            MessageManager.getString("label.reporting_dom_e_value_desc"),
+            false, 1D,
+            1E-100, 10D));
+    args.add(
+            new DoubleParameter(
+                    MessageManager
+                            .getString(HMMSearch.REPORTING_SEQ_SCORE_KEY),
+                    MessageManager.getString(
+                            "label.reporting_seq_score_desc"),
+                    false,
+                    0d, 0d, 1000d));
+    args.add(
+            new DoubleParameter(
+                    MessageManager
+                            .getString(HMMSearch.REPORTING_DOM_SCORE_KEY),
+                    MessageManager.getString(
+                            "label.reporting_dom_score_desc"),
+                    false,
+                    0d, 0d, 1000d));
+    args.add(new RadioChoiceParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_THRESHOLD_KEY),
+            null,
+            Arrays.asList(MessageManager.getString(HMMSearch.CUTOFF_EVALUE),
+                    MessageManager.getString(HMMSearch.CUTOFF_SCORE)),
+            MessageManager.getString(HMMSearch.CUTOFF_EVALUE)));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_SEQ_EVALUE_KEY),
+            MessageManager.getString("label.inclusion_seq_e_value_desc"),
+            false, 1D,
+            1E-100, 10D));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_DOM_EVALUE_KEY),
+            MessageManager.getString("label.inclusion_dom_e_value_desc"),
+            false, 1D,
+            1E-100, 10D));
+    args.add(new DoubleParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_SEQ_SCORE_KEY),
+            MessageManager.getString("label.inclusion_seq_score_desc"),
+            false, 0d, 0d,
+            1000d));
+    args.add(new DoubleParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_DOM_SCORE_KEY),
+            MessageManager.getString("label.inclusion_dom_score_desc"),
+            false, 0d, 0d,
+            1000d));
+  }
+
+  /**
+   * Answers default parameters for jackhmmer, taking into account any configured
+   * as user preferences
+   * 
+   * @param args
+   */
+  private void getJackhmmerParams(List<ArgumentI> args)
+  {
+
+    /*
+     * 'Parameters'
+     */
+    addChoiceOfSequence(args);
+
+    // addChoiceOfDatabase(args);
+
+    String database = MessageManager.getString("label.database");
+    args.add(new FileParameter(database, "", false, "", ""));
+    args.add(new IntegerParameter(
+            MessageManager.getString(HMMSearch.NUMBER_OF_ITERATIONS),
+            MessageManager.getString("label.number_of_iterations_desc"),
+            true, 5, 1, 20));
+    args.add(new RadioChoiceParameter(
+            MessageManager.getString(JackHMMER.REPORTING_CUTOFF_KEY), null,
+            Arrays.asList(MessageManager.getString(JackHMMER.CUTOFF_NONE),
+                    MessageManager.getString(JackHMMER.CUTOFF_EVALUE),
+                    MessageManager.getString(JackHMMER.CUTOFF_SCORE)),
+            MessageManager.getString(JackHMMER.CUTOFF_EVALUE)));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(JackHMMER.REPORTING_SEQ_EVALUE_KEY),
+            MessageManager.getString("label.reporting_seq_e_value_desc"),
+            false, 1D,
+            1E-38, 10D));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(JackHMMER.REPORTING_DOM_EVALUE_KEY),
+            MessageManager.getString(
+                    "label.reporting_dom_e_value_desc"),
+            false, 1D,
+            1E-38, 10D));
+    args.add(new DoubleParameter(
+            MessageManager.getString(JackHMMER.REPORTING_SEQ_SCORE_KEY),
+            MessageManager.getString("label.reporting_seq_score_desc"),
+            false, 0d, 0d,
+            1000d));
+    args.add(new DoubleParameter(
+            MessageManager.getString(JackHMMER.REPORTING_DOM_SCORE_KEY),
+            MessageManager.getString("label.reporting_dom_score_desc"),
+            false, 0d, 0d,
+            1000d));
+    args.add(new RadioChoiceParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_THRESHOLD_KEY),
+            null,
+            Arrays.asList(MessageManager.getString(HMMSearch.CUTOFF_EVALUE),
+                    MessageManager.getString(HMMSearch.CUTOFF_SCORE)),
+            MessageManager.getString(HmmerCommand.CUTOFF_EVALUE)));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_SEQ_EVALUE_KEY),
+            MessageManager.getString("label.inclusion_seq_e_value_desc"),
+            false, 1D, 1E-100, 10D));
+    args.add(new LogarithmicParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_DOM_EVALUE_KEY),
+            MessageManager.getString("label.inclusion_dom_e_value_desc"),
+            false, 1D, 1E-100, 10D));
+    args.add(new DoubleParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_SEQ_SCORE_KEY),
+            MessageManager.getString("label.inclusion_seq_score_desc"),
+            false, 0d, 0d, 1000d));
+    args.add(new DoubleParameter(
+            MessageManager.getString(HMMSearch.INCLUSION_DOM_SCORE_KEY),
+            MessageManager.getString("label.inclusion_dom_score_desc"),
+            false, 0d, 0d, 1000d));
+  }
+
+  /**
+   * Constructs a choice parameter for database to search; always includes 'this
+   * alignment', and also includes any databases held under user preferences key
+   * "HMMSEARCH_DBS" as a comma-delimited list
+   * 
+   * @param args
+   */
+  protected void addChoiceOfDatabase(List<ArgumentI> args)
+  {
+    String names = Cache.getProperty(Preferences.HMMSEARCH_DBS);
+    if (names == null || names.isEmpty())
+    {
+      return;
+    }
+
+    List<String> filePaths = new ArrayList<>();
+    List<String> fileNames = new ArrayList<>();
+
+    String thisAlignment = MessageManager.getString(HMMSearch.THIS_ALIGNMENT_KEY);
+    filePaths.add(thisAlignment);
+    fileNames.add(thisAlignment);
+
+    Scanner nameScanner = new Scanner(names);
+    nameScanner.useDelimiter(Preferences.COMMA);
+
+    while (nameScanner.hasNext())
+    {
+      String next = nameScanner.next();
+      if ("null".equals(next))
+      {
+        Cache.setProperty(Preferences.HMMSEARCH_DBS, "");
+      }
+      else
+      {
+        filePaths.add(next);
+        int pos = next.lastIndexOf(File.separator);
+        String fileName = next.substring(pos + 1);
+        fileNames.add(fileName);
+      }
+    }
+    nameScanner.close();
+    ArgumentI databasesOption = new StringParameter(
+            MessageManager.getString(HMMSearch.DATABASE_KEY),
+            MessageManager.getString("label.database_for_hmmsearch"), true,
+            thisAlignment,
+            thisAlignment,
+            filePaths, fileNames);
+    args.add(databasesOption);
+  }
+
+  /**
+   * 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, null);
+      args.add(arg);
+    }
+  }
+
+  /**
+   * Adds an argument representing the choice of sequence against which to perform
+   * jackhmmer
+   * 
+   * @param args
+   */
+  protected void addChoiceOfSequence(List<ArgumentI> args)
+  {
+    List<SequenceI> sequences = viewport.getAlignment().getSequences();
+
+    List<String> options = new ArrayList<>();
+
+    for (SequenceI seq : sequences)
+    {
+      options.add(seq.getName());
+    }
+
+    String defseq = options.get(0);
+    ArgumentI arg = new StringParameter(
+            MessageManager.getString("label.use_sequence"), null, true,
+            defseq,
+            defseq, options, null);
+    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())
+    {
+      List<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..f05823e
--- /dev/null
@@ -0,0 +1,318 @@
+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.Desktop;
+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 javax.swing.JOptionPane;
+
+public class HMMSearch extends Search
+{
+
+  boolean realign = false;
+
+  boolean trim = false;
+
+  boolean returnNoOfNewSeqs = false;
+
+  int seqsToReturn = Integer.MAX_VALUE;
+
+
+  /**
+   * 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();
+    long msgId = System.currentTimeMillis();
+    af.setProgressBar(MessageManager.getString("status.running_search"),
+            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);
+    buildArguments(args, searchOutputFile, hitsAlignmentFile, hmmFile);
+
+    return runCommand(args);
+  }
+
+
+  /**
+   * Imports the data from the temporary file to which the output of hmmsearch
+   * was directed. The results are optionally realigned using hmmalign.
+   * 
+   * @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();
+
+      readDomainTable(searchOutputFile, false);
+
+      if (searchAlignment)
+      {
+        recoverSequences(sequencesHash, seqs);
+      }
+
+      // look for PP cons and ref seq in alignment only annotation
+      AlignmentAnnotation modelpos = null, ppcons = null;
+      for (AlignmentAnnotation aa : file.getAnnotations())
+      {
+        if (aa.sequenceRef == null)
+        {
+          if (aa.label.equals("Reference Positions")) // RF feature type in
+                                                      // stockholm parser
+          {
+            modelpos = aa;
+          }
+          if (aa.label.equals("Posterior Probability"))
+          {
+            ppcons = aa;
+          }
+        }
+      }
+
+
+      int seqCount = Math.min(seqs.length, seqsToReturn);
+      SequenceI[] hmmAndSeqs = new SequenceI[seqCount + 1];
+      hmmSeq = hmmSeq.deriveSequence(); // otherwise all bad things happen
+      hmmAndSeqs[0] = hmmSeq;
+      System.arraycopy(seqs, 0, hmmAndSeqs, 1, seqCount);
+      if (modelpos != null)
+      {
+        // TODO need - get ungapped sequence method
+        hmmSeq.setSequence(
+                hmmSeq.getDatasetSequence().getSequenceAsString());
+        Annotation[] refpos = modelpos.annotations;
+        // insert gaps to match with refseq positions
+        int gc = 0, lcol = 0;
+        for (int c = 0; c < refpos.length; c++)
+        {
+          if (refpos[c] != null && ("x".equals(refpos[c].displayCharacter)))
+          {
+            if (gc > 0)
+            {
+              hmmSeq.insertCharAt(lcol + 1, gc, '-');
+            }
+            gc = 0;
+            lcol = c;
+          }
+          else
+          {
+            gc++;
+          }
+        }
+      }
+
+      if (realign)
+      {
+        realignResults(hmmAndSeqs);
+      }
+      else
+      {
+        AlignmentI al = new Alignment(hmmAndSeqs);
+        if (ppcons != null)
+        {
+          al.addAnnotation(ppcons);
+        }
+        if (modelpos != null)
+        {
+          al.addAnnotation(modelpos);
+        }
+        AlignFrame alignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
+                AlignFrame.DEFAULT_HEIGHT);
+        String ttl = "hmmSearch of " + databaseName + " using "
+                + hmmSeq.getName();
+        Desktop.addInternalFrame(alignFrame, ttl, AlignFrame.DEFAULT_WIDTH,
+                AlignFrame.DEFAULT_HEIGHT);
+
+        if (returnNoOfNewSeqs)
+        {
+          int nNew = checkForNewSequences();
+          JvOptionPane.showMessageDialog(af.alignPanel, nNew + " "
+                  + MessageManager.getString("label.new_returned"));
+        }
+
+      }
+
+
+      hmmTemp.delete();
+      inputAlignmentTemp.delete();
+      searchOutputFile.delete();
+    } finally
+    {
+      if (br != null)
+      {
+        br.close();
+      }
+    }
+  }
+
+  private int checkForNewSequences()
+  {
+    int nNew = seqs.length;
+
+    for (SequenceI resultSeq : seqs)
+    {
+      for (SequenceI aliSeq : alignment.getSequencesArray())
+      {
+        if (resultSeq.getName().equals(aliSeq.getName()))
+        {
+          nNew--;
+          break;
+        }
+      }
+    }
+
+    return nNew;
+
+  }
+
+  /**
+   * Realigns the given sequences using hmmalign, to the HMM profile sequence
+   * which is the first in the array, and opens the results in a new frame
+   * 
+   * @param hmmAndSeqs
+   */
+  protected void realignResults(SequenceI[] hmmAndSeqs)
+  {
+    /*
+     * 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 alignTo = hmmAndSeqs[0].getName();
+    List<String> options = Collections.singletonList(alignTo);
+    Option option = new Option(MessageManager.getString("label.use_hmm"),
+            "", true, alignTo, alignTo, 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();
+
+    if (returnNoOfNewSeqs)
+    {
+      int nNew = checkForNewSequences();
+      JvOptionPane.showMessageDialog(frame.alignPanel,
+              nNew + " " + MessageManager.getString("label.new_returned"));
+    }
+  }
+
+}
diff --git a/src/jalview/hmmer/HmmerCommand.java b/src/jalview/hmmer/HmmerCommand.java
new file mode 100644 (file)
index 0000000..b311b76
--- /dev/null
@@ -0,0 +1,536 @@
+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.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.JvOptionPane;
+import jalview.gui.Preferences;
+import jalview.io.FastaFile;
+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.nio.file.Paths;
+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;
+
+  /*
+   * 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 NUMBER_OF_ITERATIONS = "label.number_of_iterations";
+
+  static final String TRIM_TERMINI_KEY = "label.trim_termini";
+
+  static final String RETURN_N_NEW_SEQ = "label.check_for_new_sequences";
+
+  static final String REPORTING_CUTOFF_KEY = "label.reporting_cutoff";
+
+  static final String CUTOFF_NONE = "label.default";
+
+  static final String CUTOFF_SCORE = "label.score";
+
+  static final String CUTOFF_EVALUE = "label.evalue";
+
+  static final String REPORTING_SEQ_EVALUE_KEY = "label.reporting_seq_evalue";
+
+  static final String REPORTING_DOM_EVALUE_KEY = "label.reporting_dom_evalue";
+
+  static final String REPORTING_SEQ_SCORE_KEY = "label.reporting_seq_score";
+
+  static final String REPORTING_DOM_SCORE_KEY = "label.reporting_dom_score";
+
+  static final String INCLUSION_SEQ_EVALUE_KEY = "label.inclusion_seq_evalue";
+
+  static final String INCLUSION_DOM_EVALUE_KEY = "label.inclusion_dom_evalue";
+
+  static final String INCLUSION_SEQ_SCORE_KEY = "label.inclusion_seq_score";
+
+  static final String INCLUSION_DOM_SCORE_KEY = "label.inclusion_dom_score";
+
+  static final String ARG_TRIM = "--trim";
+
+  static final String INCLUSION_THRESHOLD_KEY = "label.inclusion_threshold";
+
+  /**
+   * 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
+      if (Platform.isWindows())
+      {
+        String path = pb.environment().get("Path");
+        path = jalview.bin.Cache.getProperty("CYGWIN_PATH") + ";" + path;
+        pb.environment().put("Path", path);
+      }
+      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("C:\Users\tva\run");
+    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, removing all HMM sequences
+   * 
+   * @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);
+          }
+        }
+      }
+    }
+
+    for (SequenceI seq : newAl.getSequencesArray())
+    {
+      if (seq.getAnnotation() != null)
+      {
+        for (AlignmentAnnotation ann : seq.getAnnotation())
+        {
+          seq.removeAlignmentAnnotation(ann);
+        }
+      }
+    }
+
+    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
+   * @throws IOException
+   */
+  protected String getCommandPath(String cmd)
+          throws IOException
+  {
+    String binariesFolder = Cache.getProperty(Preferences.HMMER_PATH);
+    // ensure any symlink to the directory is resolved:
+    binariesFolder = Paths.get(binariesFolder).toRealPath().toString();
+    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, true);
+  }
+
+  /**
+   * 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();
+    }
+  }
+
+  // TODO is needed?
+  /**
+   * Exports a sequence to the specified file
+   * 
+   * @param hmm
+   * @param hmmFile
+   * @throws IOException
+   */
+  public void exportSequence(SequenceI seq, File seqFile) throws IOException
+  {
+    if (seq != null)
+    {
+      FastaFile file = new FastaFile();
+      PrintWriter writer = new PrintWriter(seqFile);
+      writer.print(file.print(new SequenceI[] { seq }, false));
+      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 the query sequence the user selected (default is just the first
+   * sequence in the alignment)
+   * 
+   * @return
+   */
+  protected SequenceI getSequence()
+  {
+    String alignToParamName = MessageManager
+            .getString("label.use_sequence");
+    for (ArgumentI arg : params)
+    {
+      String name = arg.getName();
+      if (name.equals(alignToParamName))
+      {
+        String seqName = arg.getValue();
+        SequenceI seq = alignment.findName(seqName);
+        return seq;
+      }
+    }
+    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
+   * @param isInCygwin
+   *                     True if file is to be read/written from within the Cygwin
+   *                     shell. Should be false for any imports.
+   * @return
+   */
+  protected String getFilePath(File resultFile, boolean isInCygwin)
+  {
+    String path = resultFile.getAbsolutePath();
+    if (Platform.isWindows() && isInCygwin)
+    {
+      // 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;
+  }
+
+  /**
+   * 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);
+      }
+    }
+  }
+
+  /**
+   * Sets the names of any duplicates within the given sequences to include their
+   * respective lengths. Deletes any duplicates that have the same name after this
+   * step
+   * 
+   * @param seqs
+   */
+  void renameDuplicates(AlignmentI al)
+  {
+
+    SequenceI[] seqs = al.getSequencesArray();
+    List<Boolean> wasRenamed = new ArrayList<>();
+
+    for (SequenceI seq : seqs)
+    {
+      wasRenamed.add(false);
+    }
+
+    for (int i = 0; i < seqs.length; i++)
+    {
+      for (int j = 0; j < seqs.length; j++)
+      {
+        if (seqs[i].getName().equals(seqs[j].getName()) && i != j
+                && !wasRenamed.get(j))
+        {
+
+          wasRenamed.set(i, true);
+          String range = "/" + seqs[j].getStart() + "-" + seqs[j].getEnd();
+          // setting sequence name to include range - to differentiate between
+          // sequences of the same name. Currently have to include the range twice
+          // because the range is removed (once) when setting the name
+          // TODO come up with a better way of doing this
+          seqs[j].setName(seqs[j].getName() + range + range);
+        }
+
+      }
+      if (wasRenamed.get(i))
+      {
+        String range = "/" + seqs[i].getStart() + "-" + seqs[i].getEnd();
+        seqs[i].setName(seqs[i].getName() + range + range);
+      }
+    }
+
+    for (int i = 0; i < seqs.length; i++)
+    {
+      for (int j = 0; j < seqs.length; j++)
+      {
+        if (seqs[i].getName().equals(seqs[j].getName()) && i != j)
+        {
+          al.deleteSequence(j);
+        }
+      }
+    }
+  }
+
+}
diff --git a/src/jalview/hmmer/JackHMMER.java b/src/jalview/hmmer/JackHMMER.java
new file mode 100644 (file)
index 0000000..12c0492
--- /dev/null
@@ -0,0 +1,179 @@
+package jalview.hmmer;
+
+import jalview.bin.Cache;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
+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 java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JOptionPane;
+
+public class JackHMMER extends Search
+{
+
+  SequenceI seq = null;
+
+  /**
+   * Constructor for the JackhmmerThread
+   * 
+   * @param af
+   */
+  public JackHMMER(AlignFrame af, List<ArgumentI> args)
+  {
+    super(af, args);
+  }
+
+  /**
+   * Runs the JackhmmerThread: 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()
+  {
+    seq = getSequence();
+    if (seq == null)
+    {
+      // shouldn't happen if we got this far
+      Cache.log.error("Error: no sequence for jackhmmer");
+      return;
+    }
+
+    long msgId = System.currentTimeMillis();
+    af.setProgressBar(MessageManager.getString("status.running_search"),
+            msgId);
+
+    try
+    {
+      File seqFile = FileUtils.createTempFile("seq", ".sto");
+      File hitsAlignmentFile = FileUtils.createTempFile("hitAlignment",
+              ".sto");
+      File searchOutputFile = FileUtils.createTempFile("searchOutput",
+              ".txt");
+
+      exportStockholm(new SequenceI[] { seq }, seqFile.getAbsoluteFile(),
+              null);
+
+      boolean ran = runCommand(searchOutputFile, hitsAlignmentFile,
+              seqFile);
+      if (!ran)
+      {
+        JvOptionPane.showInternalMessageDialog(af, MessageManager
+                .formatMessage("warn.command_failed", "jackhmmer"));
+        return;
+      }
+
+      importData(hitsAlignmentFile, seqFile, 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 jackhmmer search with the given sequence 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 seqFile
+   * 
+   * @return
+   * @throws IOException
+   */
+  private boolean runCommand(File searchOutputFile, File hitsAlignmentFile,
+          File seqFile) throws IOException
+  {
+    String command = getCommandPath(JACKHMMER);
+    if (command == null)
+    {
+      return false;
+    }
+
+    List<String> args = new ArrayList<>();
+    args.add(command);
+    buildArguments(args, searchOutputFile, hitsAlignmentFile, seqFile);
+
+    return runCommand(args);
+  }
+
+  /**
+   * Imports the data from the temporary file to which the output of jackhmmer was
+   * directed.
+   */
+  private void importData(File inputAlignmentTemp, File seqTemp,
+          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();
+
+      readDomainTable(searchOutputFile, true);
+
+      if (searchAlignment)
+      {
+        recoverSequences(sequencesHash, seqs);
+      }
+
+
+
+      int seqCount = seqs.length;
+
+
+      AlignmentI al = new Alignment(seqs);
+
+      AlignFrame alignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
+              AlignFrame.DEFAULT_HEIGHT);
+      String ttl = "jackhmmer search of " + databaseName + " using "
+              + seqs[0].getName();
+      Desktop.addInternalFrame(alignFrame, ttl, AlignFrame.DEFAULT_WIDTH,
+              AlignFrame.DEFAULT_HEIGHT);
+
+      seqTemp.delete();
+      inputAlignmentTemp.delete();
+      searchOutputFile.delete();
+    } finally
+    {
+      if (br != null)
+      {
+        br.close();
+      }
+    }
+  }
+
+
+
+
+}
diff --git a/src/jalview/hmmer/Search.java b/src/jalview/hmmer/Search.java
new file mode 100644 (file)
index 0000000..ceb79e5
--- /dev/null
@@ -0,0 +1,394 @@
+package jalview.hmmer;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.util.FileUtils;
+import jalview.util.MessageManager;
+import jalview.ws.params.ArgumentI;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Scanner;
+
+public abstract class Search extends HmmerCommand
+{
+
+  static final String JACKHMMER = "jackhmmer";
+
+  static final String HMMSEARCH = "hmmsearch";
+
+  boolean realign = false;
+
+  boolean trim = false;
+
+  SequenceI[] seqs;
+
+  String databaseName;
+
+  boolean searchAlignment = true;
+
+  Hashtable sequencesHash;
+
+  public Search(AlignFrame alignFrame, List<ArgumentI> args)
+  {
+    super(alignFrame, args);
+  }
+
+  @Override
+  public void run()
+  {
+  }
+
+  /*
+  void readOutputFile(File inputTableTemp) throws IOException
+  {
+    BufferedReader br = new BufferedReader(new FileReader(inputTableTemp));
+  
+  
+    String line = "";
+    while (!line.startsWith("//"))
+    {
+  
+      while (!line.startsWith(">> ") && !line.startsWith("//"))
+      {
+        line = br.readLine();
+      }
+  
+      if (line.startsWith("//"))
+      {
+        break;
+      }
+  
+      Scanner scanner = new Scanner(line);
+      String name = scanner.next();
+      name = scanner.next();
+  
+      br.readLine();
+      br.readLine();
+  
+      List<SequenceI> domains = new ArrayList<>();
+  
+      for (SequenceI seq : seqs)
+      {
+        if (seq.getName().contains(name))
+        {
+          domains.add(seq);
+        }
+      }
+  
+      if (domains.contains(getSequence()))
+      {
+        domains.remove(getSequence());
+      }
+  
+      if (domains.size() > 0)
+      {
+        readOutputTable(br, domains);
+      }
+  
+      line = br.readLine();
+    }
+  
+  }
+  
+  
+  /**
+   * Reads in the scores table output by jackhmmer and adds annotation to
+   * sequences for E-value and bit score
+   * 
+   * @param inputTableTemp
+   * @throws IOException
+   */
+  /*
+  void readOutputTable(BufferedReader br, List<SequenceI> seqs) throws IOException
+  {
+    String line = br.readLine();
+  
+    while (!"".equals(line) && line != null)
+    {
+      if ("  ------ inclusion threshold ------".equals(line))
+      {
+        line = br.readLine();
+        continue;
+      }
+  
+      Scanner scanner = new Scanner(line);
+      scanner.next();
+      scanner.next();
+      String score = scanner.next();
+  
+      scanner.next();
+  
+      String evalue = scanner.next();
+  
+      scanner.next();
+      scanner.next();
+      scanner.next();
+      scanner.next();
+  
+      int start = scanner.nextInt();
+      int end = scanner.nextInt();
+  
+      SequenceI seq = null;
+      for (SequenceI sequence : seqs)
+      {
+        if (sequence.getStart() >= start && sequence.getEnd() <= end)
+        {
+          seq = sequence;
+          break;
+        }
+      }
+  
+      if (seq != null)
+      {
+        addScoreAnnotations(evalue, score, seq);
+      }
+  
+      scanner.close();
+      line = br.readLine();
+    }
+  }
+  */
+
+  void readDomainTable(File inputTableTemp, boolean includesQuery)
+          throws IOException
+  {
+    BufferedReader br = new BufferedReader(new FileReader(inputTableTemp));
+
+    String line = br.readLine();
+    br.readLine();
+    br.readLine();
+    line = br.readLine();
+
+    int index;
+
+    if (includesQuery)
+    {
+      index = 1;
+    }
+    else
+    {
+      index = 0;
+    }
+    while (!line.startsWith("#"))
+    {
+      if (line.contains("inclusion threshold"))
+      {
+        line = br.readLine();
+        continue;
+      }
+
+      Scanner scanner = new Scanner(line);
+      String name = scanner.next();
+
+      for (int i = 0; i < 10; i++)
+      {
+        scanner.next();
+      }
+
+      String evalue = scanner.next();
+      scanner.next();
+      String score = scanner.next();
+
+      addScoreAnnotations(evalue, score, seqs[index]);
+      index++;
+
+      scanner.close();
+      line = br.readLine();
+    }
+    br.close();
+  }
+
+
+
+
+  void addScoreAnnotations(String eValue, String bitScore, SequenceI seq)
+  {
+    String label = "Search Scores";
+    String description = "Full sequence bit score and E-Value";
+
+    try
+    {
+      AlignmentAnnotation annot = new AlignmentAnnotation(label,
+              description, null);
+
+      annot.label = label;
+      annot.description = description;
+
+      annot.setCalcId(JACKHMMER);
+
+      double dEValue = Double.parseDouble(eValue);
+      annot.setEValue(dEValue);
+
+      double dBitScore = Double.parseDouble(bitScore);
+      annot.setBitScore(dBitScore);
+
+      annot.setSequenceRef(seq);
+      seq.addAlignmentAnnotation(annot);
+
+    } catch (NumberFormatException e)
+    {
+      System.err.println("Error parsing " + label + " from " + eValue
+              + " & " + bitScore);
+    }
+  }
+
+  void buildArguments(List<String> args, File searchOutputFile,
+          File hitsAlignmentFile, File queryFile) throws IOException
+  {
+    args.add("--domtblout");
+    args.add(getFilePath(searchOutputFile, true));
+    args.add("-A");
+    args.add(getFilePath(hitsAlignmentFile, true));
+
+    File databaseFile = null;
+
+    boolean useEvalueCutoff = false;
+    boolean useScoreCutoff = false;
+    String seqReportingEvalueCutoff = null;
+    String domReportingEvalueCutoff = null;
+    String seqReportingScoreCutoff = null;
+    String domReportingScoreCutoff = null;
+    String seqInclusionEvalueCutoff = null;
+    String domInclusionEvalueCutoff = null;
+    String seqInclusionScoreCutoff = null;
+    String domInclusionScoreCutoff = null;
+    databaseName = "Alignment";
+
+    if (params != null)
+    {
+      for (ArgumentI arg : params)
+      {
+        String name = arg.getName();
+
+        if (MessageManager.getString(REPORTING_CUTOFF_KEY).equals(name))
+        {
+          if (MessageManager.getString(CUTOFF_EVALUE)
+                  .equals(arg.getValue()))
+          {
+            useEvalueCutoff = true;
+          }
+          else if (MessageManager.getString(CUTOFF_SCORE)
+                  .equals(arg.getValue()))
+          {
+            useScoreCutoff = true;
+          }
+        }
+        else if (MessageManager.getString(REPORTING_SEQ_EVALUE_KEY)
+                .equals(name))
+        {
+          seqReportingEvalueCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(REPORTING_SEQ_SCORE_KEY)
+                .equals(name))
+        {
+          seqReportingScoreCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(REPORTING_DOM_EVALUE_KEY)
+                .equals(name))
+        {
+          domReportingEvalueCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(REPORTING_DOM_SCORE_KEY)
+                .equals(name))
+        {
+          domReportingScoreCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(INCLUSION_SEQ_EVALUE_KEY)
+                .equals(name))
+        {
+          seqInclusionEvalueCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(INCLUSION_SEQ_SCORE_KEY)
+                .equals(name))
+        {
+          seqInclusionScoreCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(INCLUSION_DOM_EVALUE_KEY)
+                .equals(name))
+        {
+          domInclusionEvalueCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(INCLUSION_DOM_SCORE_KEY)
+                .equals(name))
+        {
+          domInclusionScoreCutoff = arg.getValue();
+        }
+        else if (MessageManager.getString(DATABASE_KEY).equals(name))
+        {
+          databaseFile = new File(arg.getValue());
+          if (!arg.getValue().isEmpty())
+          {
+            searchAlignment = false;
+          }
+        }
+        else if (MessageManager.getString(NUMBER_OF_ITERATIONS)
+                .equals(name))
+        {
+          if (!arg.getValue().isEmpty())
+          {
+            args.add("-N");
+            args.add(arg.getValue());
+          }
+        }
+      }
+    }
+
+    if (useEvalueCutoff)
+    {
+      args.add("-E");
+      args.add(seqReportingEvalueCutoff);
+      args.add("--domE");
+      args.add(domReportingEvalueCutoff);
+
+      args.add("--incE");
+      args.add(seqInclusionEvalueCutoff);
+      args.add("--incdomE");
+      args.add(domInclusionEvalueCutoff);
+    }
+    else if (useScoreCutoff)
+    {
+      args.add("-T");
+      args.add(seqReportingScoreCutoff);
+      args.add("--domT");
+      args.add(domReportingScoreCutoff);
+
+      args.add("--incT");
+      args.add(seqInclusionEvalueCutoff);
+      args.add("--incdomT");
+      args.add(domInclusionEvalueCutoff);
+    }
+
+    // if (!dbFound || MessageManager.getString(THIS_ALIGNMENT_KEY)
+    // .equals(dbPath))
+    if (searchAlignment)
+    {
+      /*
+       * no external database specified for search, so
+       * export current alignment as 'database' to search
+       */
+      databaseFile = FileUtils.createTempFile("database", ".sto");
+      AlignmentI al = af.getViewport().getAlignment();
+      AlignmentI copy = new Alignment(al);
+
+      deleteHmmSequences(copy);
+
+      if (searchAlignment)
+      {
+        sequencesHash = stashSequences(copy.getSequencesArray());
+      }
+
+      exportStockholm(copy.getSequencesArray(), databaseFile, null);
+    }
+
+    args.add(getFilePath(queryFile, true));
+    args.add(getFilePath(databaseFile, true));
+  }
+}
index 497f0a5..5e15223 100755 (executable)
@@ -322,9 +322,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;
   }
 
@@ -337,7 +337,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++)
     {
@@ -408,7 +408,7 @@ public abstract class AlignFile extends FileParse
   {
     if (newickStrings == null)
     {
-      newickStrings = new Vector<String[]>();
+      newickStrings = new Vector<>();
     }
     newickStrings.addElement(new String[] { treeName, newickString });
   }
@@ -432,4 +432,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;
+  }
+
 }
diff --git a/src/jalview/io/CountReader.java b/src/jalview/io/CountReader.java
new file mode 100644 (file)
index 0000000..eea3dae
--- /dev/null
@@ -0,0 +1,63 @@
+package jalview.io;
+
+import jalview.bin.Jalview;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ResidueCount;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
+import jalview.util.MessageManager;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import javax.swing.JFileChooser;
+
+public class CountReader
+{
+  public static ResidueCount getBackgroundFrequencies(AlignmentPanel ap, SequenceI seq) throws MalformedURLException, IOException
+  {
+    JFileChooser bkgdFreqChooser = new JFileChooser();
+    
+    bkgdFreqChooser.showOpenDialog(ap);
+    
+    File file = bkgdFreqChooser.getSelectedFile();
+    if (file == null)
+    {
+      return null;
+    }
+    
+    IdentifyFile identifier = new IdentifyFile();
+    FileFormatI format = null;
+    try
+    {
+      format = identifier.identify(file.getPath(), DataSourceType.FILE);
+    } catch (Exception e)
+    {
+
+    }
+    
+    if (format == null)
+    {
+      if (!Jalview.isHeadlessMode())
+      {
+        JvOptionPane.showInternalMessageDialog(Desktop.desktop,
+                MessageManager.getString("label.couldnt_read_data") + " in "
+                        + file + "\n"
+                        + AppletFormatAdapter.getSupportedFormats(),
+                MessageManager.getString("label.couldnt_read_data"),
+                JvOptionPane.WARNING_MESSAGE);
+      }
+    }
+
+    FileParse parser = new FileParse(file.getPath(), DataSourceType.FILE);
+    AlignmentI al = new FormatAdapter().readFromFile(parser, format);
+    parser.close();
+    
+    ResidueCount counts = new ResidueCount(al.getSequences());
+    
+    return counts;
+  }
+}
index e94e1ce..7a581c1 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 3afbaad..b6701a3 100755 (executable)
@@ -43,13 +43,16 @@ import jalview.ws.utils.UrlDownloadClient;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.StringTokenizer;
-import java.util.Vector;
 
 import javax.swing.SwingUtilities;
 
 public class FileLoader implements Runnable
 {
+  private static final String TAB = "\t";
+
   String file;
 
   DataSourceType protocol;
@@ -202,56 +205,95 @@ public class FileLoader implements Runnable
     return alignFrame;
   }
 
-  public void updateRecentlyOpened()
+  public void LoadFileOntoAlignmentWaitTillLoaded(AlignViewport viewport,
+          String file, DataSourceType sourceType, FileFormatI format)
   {
-    Vector recent = new Vector();
-    if (protocol == DataSourceType.PASTE)
+    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())
     {
-      // do nothing if the file was pasted in as text... there is no filename to
-      // refer to it as.
-      return;
+      try
+      {
+        Thread.sleep(500);
+      } catch (Exception ex)
+      {
+      }
     }
-    if (file != null
-            && file.indexOf(System.getProperty("java.io.tmpdir")) > -1)
+  }
+
+  /**
+   * Updates (or creates) the tab-separated list of recently opened files held
+   * under the given property name by inserting the filePath at the front of the
+   * list. Duplicates are removed, and the list is limited to 11 entries. The
+   * method returns the updated value of the property.
+   * 
+   * @param filePath
+   * @param sourceType
+   */
+  public static String updateRecentlyOpened(String filePath,
+          DataSourceType sourceType)
+  {
+    if (sourceType != DataSourceType.FILE
+            && sourceType != DataSourceType.URL)
     {
-      // ignore files loaded from the system's temporary directory
-      return;
+      return null;
     }
-    String type = protocol == DataSourceType.FILE ? "RECENT_FILE"
-            : "RECENT_URL";
 
-    String historyItems = jalview.bin.Cache.getProperty(type);
+    String propertyName = sourceType == DataSourceType.FILE ? "RECENT_FILE"
+            : "RECENT_URL";
+    String historyItems = Cache.getProperty(propertyName);
+    if (filePath != null
+            && filePath.indexOf(System.getProperty("java.io.tmpdir")) > -1)
+    {
+      // ignore files loaded from the system's temporary directory
+      return null;
+    }
 
-    StringTokenizer st;
+    List<String> recent = new ArrayList<>();
 
     if (historyItems != null)
     {
-      st = new StringTokenizer(historyItems, "\t");
+      StringTokenizer st = new StringTokenizer(historyItems, TAB);
 
       while (st.hasMoreTokens())
       {
-        recent.addElement(st.nextElement().toString().trim());
+        String trimmed = st.nextToken().trim();
+        if (!recent.contains(trimmed))
+        {
+          recent.add(trimmed);
+        }
       }
     }
 
-    if (recent.contains(file))
+    /*
+     * if file was already in the list, it moves to the top
+     */
+    if (recent.contains(filePath))
     {
-      recent.remove(file);
+      recent.remove(filePath);
     }
 
-    StringBuffer newHistory = new StringBuffer(file);
+    StringBuilder newHistory = new StringBuilder(filePath);
     for (int i = 0; i < recent.size() && i < 10; i++)
     {
-      newHistory.append("\t");
-      newHistory.append(recent.elementAt(i));
+      newHistory.append(TAB);
+      newHistory.append(recent.get(i));
     }
 
-    Cache.setProperty(type, newHistory.toString());
+    String newProperty = newHistory.toString();
+    Cache.setProperty(propertyName, newProperty);
 
-    if (protocol == DataSourceType.FILE)
-    {
-      Cache.setProperty("DEFAULT_FILE_FORMAT", format.getName());
-    }
+    return newProperty;
   }
 
   @Override
@@ -397,6 +439,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.getHeight() - 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
           {
@@ -500,7 +558,12 @@ public class FileLoader implements Runnable
         }
       }
 
-      updateRecentlyOpened();
+      updateRecentlyOpened(file, protocol);
+
+      if (protocol == DataSourceType.FILE && format != null)
+      {
+        Cache.setProperty("DEFAULT_FILE_FORMAT", format.getName());
+      }
 
     } catch (Exception er)
     {
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 5a55b5b..61b7491 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.io;
 
 import jalview.api.FeatureColourI;
+import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.DBRefSource;
 import jalview.datamodel.GeneLociI;
@@ -64,7 +65,7 @@ public class SequenceAnnotationReport
    * Comparator to order DBRefEntry by Source + accession id (case-insensitive),
    * with 'Primary' sources placed before others, and 'chromosome' first of all
    */
-  private static Comparator<DBRefEntry> comparator = new Comparator<DBRefEntry>()
+  private static Comparator<DBRefEntry> comparator = new Comparator<>()
   {
 
     @Override
@@ -379,12 +380,27 @@ public class SequenceAnnotationReport
       sb.append("<br>").append(tmp);
       maxWidth = Math.max(maxWidth, tmp.length());
     }
+
     SequenceI ds = sequence;
     while (ds.getDatasetSequence() != null)
     {
       ds = ds.getDatasetSequence();
     }
 
+    /*
+     * add any annotation scores
+     */
+    AlignmentAnnotation[] anns = ds.getAnnotation();
+    for (int i = 0; anns != null && i < anns.length; i++)
+    {
+      AlignmentAnnotation aa = anns[i];
+      if (aa != null && aa.hasScore() && aa.sequenceRef != null)
+      {
+        sb.append("<br>").append(aa.label).append(": ")
+                .append(aa.getScore());
+      }
+    }
+
     if (showDbRefs)
     {
       maxWidth = Math.max(maxWidth, appendDbRefs(sb, ds, summary));
@@ -404,7 +420,24 @@ public class SequenceAnnotationReport
         maxWidth = Math.max(maxWidth, sz);
       }
     }
+
+
+    if (sequence.getAnnotation("Search Scores") != null)
+    {
+      sb.append("<br>");
+      String eValue = " E-Value: "
+              + sequence.getAnnotation("Search Scores")[0].getEValue();
+      String bitScore = " Bit Score: "
+              + sequence.getAnnotation("Search Scores")[0].getBitScore();
+      sb.append(eValue);
+      sb.append("<br>");
+      sb.append(bitScore);
+      maxWidth = Math.max(maxWidth, eValue.length());
+      maxWidth = Math.max(maxWidth, bitScore.length());
+    }
+    sb.append("<br>");
     sb.append("</i>");
+
     return maxWidth;
   }
 
index 0e73af1..f7a2df2 100644 (file)
@@ -76,10 +76,15 @@ public class StockholmFile extends AlignFile
 {
   private static final String ANNOTATION = "annotation";
 
+  private static final char UNDERSCORE = '_';
+  
   private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
 
   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(
           "(<|>|\\[|\\]|\\(|\\)|\\{|\\})");
 
@@ -93,14 +98,14 @@ public class StockholmFile extends AlignFile
 
   StringBuffer out; // output buffer
 
-  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)
   {
@@ -227,7 +232,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
@@ -635,14 +640,15 @@ public class StockholmFile extends AlignFile
             if (features.containsKey(this.id2type(type)))
             {
               // logger.debug("Found content for " + this.id2type(type));
-              content = (Hashtable) features.get(this.id2type(type));
+              content = (Hashtable) features
+                      .get(this.id2type(type));
             }
             else
             {
               // logger.debug("Creating new content holder for " +
               // this.id2type(type));
               content = new Hashtable();
-              features.put(this.id2type(type), content);
+              features.put(id2type(type), content);
             }
             String ns = (String) content.get(ANNOTATION);
 
@@ -817,10 +823,9 @@ 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, convert2 = null;
+    // String convert1 = OPEN_PAREN.replaceAll(annots);
+    // String convert2 = CLOSE_PAREN.replaceAll(convert1);
     // annots = convert2;
 
     String type = label;
@@ -834,6 +839,7 @@ public class StockholmFile extends AlignFile
     type = id2type(type);
 
     boolean isrnass = false;
+
     if (type.equalsIgnoreCase("secondary structure"))
     {
       ss = true;
@@ -850,6 +856,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
@@ -1016,36 +1026,40 @@ public class StockholmFile extends AlignFile
       if (alAnot != null)
       {
         Annotation[] ann;
+
         for (int j = 0; j < alAnot.length; j++)
         {
-
-          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)
+          if (alAnot[j].annotations != null)
           {
+            String key = type2id(alAnot[j].label);
+            boolean isrna = alAnot[j].isValidStruc();
 
-            continue;
-          }
+            if (isrna)
+            {
+              // hardwire to secondary structure if there is RNA secondary
+              // structure on the annotation
+              key = "SS";
+            }
+            if (key == null)
+            {
 
-          // 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]);
+              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(seq);
+            out.append(newline);
           }
-          out.append(seq);
-          out.append(newline);
         }
+
       }
 
       out.append(new Format("%-" + maxid + "s")
@@ -1109,6 +1123,7 @@ public class StockholmFile extends AlignFile
     return out.toString();
   }
 
+
   /**
    * add an annotation character to the output row
    * 
@@ -1176,6 +1191,26 @@ public class StockholmFile extends AlignFile
             : seq;
   }
 
+  /**
+   * make a friendly ID string.
+   * 
+   * @param dataName
+   * @return truncated dataName to after last '/'
+   */
+  private String safeName(String dataName)
+  {
+    int b = 0;
+    while ((b = dataName.indexOf("/")) > -1 && b < dataName.length())
+    {
+      dataName = dataName.substring(b + 1).trim();
+
+    }
+    int e = (dataName.length() - dataName.indexOf(".")) + 1;
+    dataName = dataName.substring(1, e).trim();
+    return dataName;
+  }
+  
+  
   public String print()
   {
     out = new StringBuffer();
@@ -1213,7 +1248,7 @@ public class StockholmFile extends AlignFile
 
     }
   }
-
+  
   protected static String id2type(String id)
   {
     if (typeIds.containsKey(id))
@@ -1246,23 +1281,4 @@ public class StockholmFile extends AlignFile
             "Warning : Unknown Stockholm annotation type: " + type);
     return key;
   }
-
-  /**
-   * make a friendly ID string.
-   * 
-   * @param dataName
-   * @return truncated dataName to after last '/'
-   */
-  private String safeName(String dataName)
-  {
-    int b = 0;
-    while ((b = dataName.indexOf("/")) > -1 && b < dataName.length())
-    {
-      dataName = dataName.substring(b + 1).trim();
-
-    }
-    int e = (dataName.length() - dataName.indexOf(".")) + 1;
-    dataName = dataName.substring(1, e).trim();
-    return dataName;
-  }
 }
index 075b490..579da08 100755 (executable)
@@ -27,6 +27,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.schemes.ResidueColourScheme;
 import jalview.util.MessageManager;
@@ -42,6 +44,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;
 
@@ -69,6 +72,8 @@ public class GAlignFrame extends JInternalFrame
 
   protected JMenu webService = new JMenu();
 
+  protected JMenu hmmerMenu = new JMenu();
+
   protected JMenuItem webServiceNoServices;
 
   protected JCheckBoxMenuItem viewBoxesMenuItem = new JCheckBoxMenuItem();
@@ -197,6 +202,12 @@ 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;
@@ -251,7 +262,7 @@ public class GAlignFrame extends JInternalFrame
   private void jbInit() throws Exception
   {
     initColourMenu();
-
+  
     JMenuItem saveAs = new JMenuItem(
             MessageManager.getString("action.save_as"));
     ActionListener al = new ActionListener()
@@ -262,14 +273,14 @@ public class GAlignFrame extends JInternalFrame
         saveAs_actionPerformed(e);
       }
     };
-
+  
     // FIXME getDefaultToolkit throws an exception in Headless mode
     KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S,
             jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx()
                     | jalview.util.ShortcutKeyMaskExWrapper.SHIFT_DOWN_MASK,
             false);
     addMenuActionAndAccelerator(keyStroke, saveAs, al);
-
+  
     closeMenuItem.setText(MessageManager.getString("action.close"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_W,
             jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx(), false);
@@ -282,7 +293,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(
@@ -292,6 +303,9 @@ public class GAlignFrame extends JInternalFrame
     JMenu calculateMenu = new JMenu(
             MessageManager.getString("action.calculate"));
     webService.setText(MessageManager.getString("action.web_service"));
+
+    initHMMERMenu();
+
     JMenuItem selectAllSequenceMenuItem = new JMenuItem(
             MessageManager.getString("action.select_all"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A,
@@ -305,7 +319,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);
@@ -318,7 +332,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,
@@ -332,7 +346,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, invertSequenceMenuItem, al);
-
+  
     JMenuItem grpsFromSelection = new JMenuItem(
             MessageManager.getString("action.make_groups_selection"));
     grpsFromSelection.addActionListener(new ActionListener()
@@ -368,7 +382,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,
@@ -382,7 +396,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,
@@ -396,7 +410,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,
@@ -412,7 +426,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, removeAllGapsMenuItem, al);
-
+  
     JMenuItem justifyLeftMenuItem = new JMenuItem(
             MessageManager.getString("action.left_justify_alignment"));
     justifyLeftMenuItem.addActionListener(new ActionListener()
@@ -504,7 +518,27 @@ public class GAlignFrame extends JInternalFrame
         sortGroupMenuItem_actionPerformed(e);
       }
     });
-
+    JMenuItem sortEValueMenuItem = new JMenuItem(
+            MessageManager.getString("action.by_evalue"));
+    sortEValueMenuItem.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        sortEValueMenuItem_actionPerformed(e);
+      }
+    });
+    JMenuItem sortBitScoreMenuItem = new JMenuItem(
+            MessageManager.getString("action.by_bit_score"));
+    sortBitScoreMenuItem.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        sortBitScoreMenuItem_actionPerformed(e);
+      }
+    });
+  
     JMenuItem removeRedundancyMenuItem = new JMenuItem(
             MessageManager.getString("action.remove_redundancy"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_D,
@@ -519,6 +553,30 @@ public class GAlignFrame extends JInternalFrame
     };
     addMenuActionAndAccelerator(keyStroke, removeRedundancyMenuItem, al);
 
+    JMenuItem filterByEValue = new JMenuItem(
+            MessageManager.getString("action.filter_by_evalue"));
+    filterByEValue.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        filterByEValue_actionPerformed();
+      }
+
+    });
+
+    JMenuItem filterByScore = new JMenuItem(
+            MessageManager.getString("action.filter_by_score"));
+    filterByScore.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        filterByScore_actionPerformed();
+      }
+
+    });
+  
     JMenuItem pairwiseAlignmentMenuItem = new JMenuItem(
             MessageManager.getString("action.pairwise_alignment"));
     pairwiseAlignmentMenuItem.addActionListener(new ActionListener()
@@ -529,16 +587,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"));
@@ -606,6 +666,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()
@@ -646,7 +707,7 @@ public class GAlignFrame extends JInternalFrame
         colourTextMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem htmlMenuItem = new JMenuItem(
             MessageManager.getString("label.html"));
     htmlMenuItem.addActionListener(new ActionListener()
@@ -657,7 +718,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()
@@ -668,7 +729,7 @@ public class GAlignFrame extends JInternalFrame
         bioJSMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem overviewMenuItem = new JMenuItem(
             MessageManager.getString("label.overview_window"));
     overviewMenuItem.addActionListener(new ActionListener()
@@ -679,7 +740,7 @@ public class GAlignFrame extends JInternalFrame
         overviewMenuItem_actionPerformed(e);
       }
     });
-
+  
     undoMenuItem.setEnabled(false);
     undoMenuItem.setText(MessageManager.getString("action.undo"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
@@ -693,7 +754,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,
@@ -707,7 +768,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, redoMenuItem, al);
-
+  
     wrapMenuItem.setText(MessageManager.getString("label.wrap"));
     wrapMenuItem.addActionListener(new ActionListener()
     {
@@ -717,7 +778,7 @@ public class GAlignFrame extends JInternalFrame
         wrapMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem printMenuItem = new JMenuItem(
             MessageManager.getString("action.print"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_P,
@@ -731,7 +792,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, printMenuItem, al);
-
+  
     renderGapsMenuItem
             .setText(MessageManager.getString("action.show_gaps"));
     renderGapsMenuItem.setState(true);
@@ -743,7 +804,7 @@ public class GAlignFrame extends JInternalFrame
         renderGapsMenuItem_actionPerformed(e);
       }
     });
-
+  
     JMenuItem findMenuItem = new JMenuItem(
             MessageManager.getString("action.find"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_F,
@@ -762,6 +823,7 @@ public class GAlignFrame extends JInternalFrame
 
     showSeqFeatures.setText(
             MessageManager.getString("label.show_sequence_features"));
+
     showSeqFeatures.addActionListener(new ActionListener()
     {
       @Override
@@ -780,86 +842,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"));
@@ -873,7 +935,7 @@ public class GAlignFrame extends JInternalFrame
         applyAutoAnnotationSettings_actionPerformed(e);
       }
     });
-
+  
     ButtonGroup buttonGroup = new ButtonGroup();
     final JRadioButtonMenuItem showAutoFirst = new JRadioButtonMenuItem(
             MessageManager.getString("label.show_first"));
@@ -904,7 +966,7 @@ public class GAlignFrame extends JInternalFrame
         sortAnnotations_actionPerformed();
       }
     });
-
+  
     JMenuItem deleteGroups = new JMenuItem(
             MessageManager.getString("action.undefine_groups"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_U,
@@ -918,7 +980,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, deleteGroups, al);
-
+  
     JMenuItem annotationColumn = new JMenuItem(
             MessageManager.getString("action.select_by_annotation"));
     annotationColumn.addActionListener(new ActionListener()
@@ -929,7 +991,7 @@ public class GAlignFrame extends JInternalFrame
         annotationColumn_actionPerformed(e);
       }
     });
-
+  
     JMenuItem createGroup = new JMenuItem(
             MessageManager.getString("action.create_group"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_G,
@@ -943,7 +1005,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,
@@ -959,7 +1021,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, unGroup, al);
-
+  
     copy.setText(MessageManager.getString("action.copy"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_C,
             jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx(), false);
@@ -973,7 +1035,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, copy, al);
-
+  
     cut.setText(MessageManager.getString("action.cut"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_X,
             jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx(), false);
@@ -986,7 +1048,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, cut, al);
-
+  
     JMenuItem delete = new JMenuItem(
             MessageManager.getString("action.delete"));
     delete.addActionListener(new ActionListener()
@@ -997,7 +1059,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"));
@@ -1010,11 +1072,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,
@@ -1024,11 +1093,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()
     {
@@ -1040,7 +1116,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()
     {
@@ -1070,7 +1145,7 @@ public class GAlignFrame extends JInternalFrame
         createEPS(null);
       }
     });
-
+  
     JMenuItem createSVG = new JMenuItem("SVG");
     createSVG.addActionListener(new ActionListener()
     {
@@ -1080,7 +1155,7 @@ public class GAlignFrame extends JInternalFrame
         createSVG(null);
       }
     });
-
+  
     JMenuItem loadTreeMenuItem = new JMenuItem(
             MessageManager.getString("label.load_associated_tree"));
     loadTreeMenuItem.setActionCommand(
@@ -1093,7 +1168,7 @@ public class GAlignFrame extends JInternalFrame
         loadTreeMenuItem_actionPerformed(e);
       }
     });
-
+  
     scaleAbove.setVisible(false);
     scaleAbove.setText(MessageManager.getString("action.scale_above"));
     scaleAbove.addActionListener(new ActionListener()
@@ -1144,15 +1219,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"));
@@ -1163,12 +1238,12 @@ public class GAlignFrame extends JInternalFrame
       {
         buildTreeSortMenu();
       }
-
+  
       @Override
       public void menuDeselected(MenuEvent e)
       {
       }
-
+  
       @Override
       public void menuCanceled(MenuEvent e)
       {
@@ -1179,17 +1254,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)
       {
@@ -1269,7 +1344,7 @@ public class GAlignFrame extends JInternalFrame
         showReverse_actionPerformed(true);
       }
     });
-
+  
     JMenuItem extractScores = new JMenuItem(
             MessageManager.getString("label.extract_scores"));
     extractScores.addActionListener(new ActionListener()
@@ -1282,10 +1357,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"));
@@ -1297,7 +1372,7 @@ public class GAlignFrame extends JInternalFrame
         runGroovy_actionPerformed();
       }
     });
-
+  
     JMenuItem openFeatureSettings = new JMenuItem(
             MessageManager.getString("action.feature_settings"));
     openFeatureSettings.addActionListener(new ActionListener()
@@ -1318,7 +1393,7 @@ public class GAlignFrame extends JInternalFrame
         fetchSequence_actionPerformed(e);
       }
     });
-
+  
     JMenuItem associatedData = new JMenuItem(
             MessageManager.getString("label.load_features_annotations"));
     associatedData.addActionListener(new ActionListener()
@@ -1326,7 +1401,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"));
@@ -1380,7 +1462,7 @@ public class GAlignFrame extends JInternalFrame
         listenToViewSelections_actionPerformed(e);
       }
     });
-
+  
     JMenu addSequenceMenu = new JMenu(
             MessageManager.getString("label.add_sequences"));
     JMenuItem addFromFile = new JMenuItem(
@@ -1526,7 +1608,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,
@@ -1542,7 +1624,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, invertColSel, al);
-
+  
     showComplementMenuItem.setVisible(false);
     showComplementMenuItem.addActionListener(new ActionListener()
     {
@@ -1552,7 +1634,7 @@ public class GAlignFrame extends JInternalFrame
         showComplement_actionPerformed(showComplementMenuItem.getState());
       }
     });
-
+  
     tabbedPane.addChangeListener(new javax.swing.event.ChangeListener()
     {
       @Override
@@ -1573,7 +1655,7 @@ public class GAlignFrame extends JInternalFrame
           tabbedPane_mousePressed(e);
         }
       }
-
+  
       @Override
       public void mouseReleased(MouseEvent e)
       {
@@ -1591,7 +1673,7 @@ public class GAlignFrame extends JInternalFrame
         tabbedPane_focusGained(e);
       }
     });
-
+  
     JMenuItem save = new JMenuItem(MessageManager.getString("action.save"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_S,
             jalview.util.ShortcutKeyMaskExWrapper.getMenuShortcutKeyMaskEx(), false);
@@ -1604,7 +1686,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, save, al);
-
+  
     reload.setEnabled(false);
     reload.setText(MessageManager.getString("action.reload"));
     reload.addActionListener(new ActionListener()
@@ -1615,7 +1697,7 @@ public class GAlignFrame extends JInternalFrame
         reload_actionPerformed(e);
       }
     });
-
+  
     JMenuItem newView = new JMenuItem(
             MessageManager.getString("action.new_view"));
     keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_T,
@@ -1629,11 +1711,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"));
 
@@ -1647,7 +1729,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);
@@ -1660,7 +1742,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);
@@ -1673,7 +1755,7 @@ public class GAlignFrame extends JInternalFrame
       }
     };
     addMenuActionAndAccelerator(keyStroke, expandViews, al);
-
+  
     JMenuItem pageSetup = new JMenuItem(
             MessageManager.getString("action.page_setup"));
     pageSetup.addActionListener(new ActionListener()
@@ -1706,12 +1788,24 @@ public class GAlignFrame extends JInternalFrame
         selectHighlightedColumns_actionPerformed(actionEvent);
       }
     };
+    JMenuItem Filter = new JMenuItem(
+            MessageManager.getString("action.select_highlighted_columns"));
+    selectHighlighted.setToolTipText(
+            MessageManager.getString("tooltip.select_highlighted_columns"));
+    al = new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent actionEvent)
+      {
+        selectHighlightedColumns_actionPerformed(actionEvent);
+      }
+    };
     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"));
@@ -1724,7 +1818,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);
@@ -1744,7 +1839,7 @@ public class GAlignFrame extends JInternalFrame
     fileMenu.add(loadVcf);
     fileMenu.addSeparator();
     fileMenu.add(closeMenuItem);
-
+  
     pasteMenu.add(pasteNew);
     pasteMenu.add(pasteThis);
     editMenu.add(undoMenuItem);
@@ -1766,7 +1861,10 @@ public class GAlignFrame extends JInternalFrame
     // editMenu.add(justifyRightMenuItem);
     // editMenu.addSeparator();
     editMenu.add(padGapsMenuitem);
-
+    editMenu.addSeparator();
+    editMenu.add(filterByEValue);
+    editMenu.add(filterByScore);
+  
     showMenu.add(showAllColumns);
     showMenu.add(showAllSeqs);
     showMenu.add(showAllhidden);
@@ -1794,7 +1892,7 @@ public class GAlignFrame extends JInternalFrame
     viewMenu.add(alignmentProperties);
     viewMenu.addSeparator();
     viewMenu.add(overviewMenuItem);
-
+  
     annotationsMenu.add(annotationPanelMenuItem);
     annotationsMenu.addSeparator();
     annotationsMenu.add(showAllAlAnnotations);
@@ -1821,6 +1919,8 @@ public class GAlignFrame extends JInternalFrame
     sort.add(sortLengthMenuItem);
     sort.add(sortGroupMenuItem);
     sort.add(sortPairwiseMenuItem);
+    sort.add(sortEValueMenuItem);
+    sort.add(sortBitScoreMenuItem);
     sort.add(sortByTreeMenu);
     calculateMenu.add(sort);
     calculateMenu.add(calculateTree);
@@ -1838,7 +1938,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);
@@ -1853,7 +1953,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);
@@ -1887,6 +1987,170 @@ public class GAlignFrame extends JInternalFrame
     // selectMenu.add(listenToViewSelections);
   }
 
+  /**
+   * Constructs the entries on the HMMER menu
+   */
+  protected void initHMMERMenu()
+  {
+    /*
+     * hmmbuild
+     */
+    JMenu hmmBuild = new JMenu(MessageManager.getString("label.hmmbuild"));
+    JMenuItem hmmBuildSettings = new JMenuItem(
+            MessageManager.getString("label.edit_settings_and_run"));
+    hmmBuildSettings.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmBuild_actionPerformed(false);
+      }
+    });
+    JMenuItem hmmBuildRun = new JMenuItem(MessageManager.formatMessage(
+            "label.action_with_default_settings", "hmmbuild"));
+    hmmBuildRun.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmBuild_actionPerformed(true);
+      }
+    });
+    hmmBuild.add(hmmBuildRun);
+    hmmBuild.add(hmmBuildSettings);
+
+    /*
+     * hmmalign
+     */
+    JMenu hmmAlign = new JMenu(MessageManager.getString("label.hmmalign"));
+    JMenuItem hmmAlignRun = new JMenuItem(MessageManager.formatMessage(
+            "label.action_with_default_settings", "hmmalign"));
+    hmmAlignRun.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmAlign_actionPerformed(true);
+      }
+    });
+    JMenuItem hmmAlignSettings = new JMenuItem(
+            MessageManager.getString("label.edit_settings_and_run"));
+    hmmAlignSettings.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmAlign_actionPerformed(false);
+      }
+    });
+    hmmAlign.add(hmmAlignRun);
+    hmmAlign.add(hmmAlignSettings);
+
+    /*
+     * hmmsearch
+     */
+    JMenu hmmSearch = new JMenu(
+            MessageManager.getString("label.hmmsearch"));
+    JMenuItem hmmSearchSettings = new JMenuItem(
+            MessageManager.getString("label.edit_settings_and_run"));
+    hmmSearchSettings.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmSearch_actionPerformed(false);
+      }
+    });
+    JMenuItem hmmSearchRun = new JMenuItem(MessageManager.formatMessage(
+            "label.action_with_default_settings", "hmmsearch"));
+    hmmSearchRun.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        hmmSearch_actionPerformed(true);
+      }
+    });
+    JMenuItem addDatabase = new JMenuItem(
+            MessageManager.getString("label.add_database"));
+    addDatabase.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        try
+        {
+          addDatabase_actionPerformed();
+        } catch (IOException e1)
+        {
+          e1.printStackTrace();
+        }
+      }
+    });
+    hmmSearch.add(hmmSearchRun);
+    hmmSearch.add(hmmSearchSettings);
+    // hmmSearch.add(addDatabase);
+
+    /*
+     * jackhmmer
+     */
+    JMenu jackhmmer = new JMenu(
+            MessageManager.getString("label.jackhmmer"));
+    JMenuItem jackhmmerSettings = new JMenuItem(
+            MessageManager.getString("label.edit_settings_and_run"));
+    jackhmmerSettings.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        jackhmmer_actionPerformed(false);
+      }
+    });
+    JMenuItem jackhmmerRun = new JMenuItem(MessageManager.formatMessage(
+            "label.action_with_default_settings", "jackhmmer"));
+    jackhmmerRun.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        jackhmmer_actionPerformed(true);
+      }
+
+    });
+    /*
+    JMenuItem addDatabase = new JMenuItem(
+            MessageManager.getString("label.add_database"));
+    addDatabase.addActionListener(new ActionListener()
+    {
+      @Override
+      public void actionPerformed(ActionEvent e)
+      {
+        try
+        {
+          addDatabase_actionPerformed();
+        } catch (IOException e1)
+        {
+          e1.printStackTrace();
+        }
+      }
+    });
+    */
+    jackhmmer.add(jackhmmerRun);
+    jackhmmer.add(jackhmmerSettings);
+    // hmmSearch.add(addDatabase);
+
+    /*
+     * top level menu
+     */
+    hmmerMenu.setText(MessageManager.getString("action.hmmer"));
+    hmmerMenu.setEnabled(HmmerCommand.isHmmerAvailable());
+    hmmerMenu.add(hmmBuild);
+    hmmerMenu.add(hmmAlign);
+    hmmerMenu.add(hmmSearch);
+    hmmerMenu.add(jackhmmer);
+
+  }
+
   protected void loadVcf_actionPerformed()
   {
   }
@@ -2302,6 +2566,14 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
+  protected void sortEValueMenuItem_actionPerformed(ActionEvent e)
+  {
+  }
+
+  protected void sortBitScoreMenuItem_actionPerformed(ActionEvent e)
+  {
+  }
+
   protected void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
   {
   }
@@ -2363,10 +2635,12 @@ public class GAlignFrame extends JInternalFrame
   }
 
   protected void pasteNew_actionPerformed(ActionEvent e)
+          throws IOException, InterruptedException
   {
   }
 
   protected void pasteThis_actionPerformed(ActionEvent e)
+          throws IOException, InterruptedException
   {
   }
 
@@ -2374,6 +2648,27 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
+  protected void hmmBuild_actionPerformed(boolean withDefaults)
+  {
+  }
+
+  protected void hmmSearch_actionPerformed(boolean withDefaults)
+  {
+  }
+
+  protected void jackhmmer_actionPerformed(boolean b)
+  {
+  }
+
+  protected void addDatabase_actionPerformed()
+          throws FileFormatException, IOException
+  {
+  }
+
+  protected void hmmAlign_actionPerformed(boolean withDefaults)
+  {
+  }
+
   public void createPNG(java.io.File f)
   {
   }
@@ -2430,6 +2725,14 @@ public class GAlignFrame extends JInternalFrame
   {
   }
 
+  protected void filterByEValue_actionPerformed()
+  {
+  }
+
+  protected void filterByScore_actionPerformed()
+  {
+  }
+
   protected void scaleRight_actionPerformed(ActionEvent e)
   {
   }
@@ -2489,6 +2792,7 @@ public class GAlignFrame extends JInternalFrame
   }
 
   public void associatedData_actionPerformed(ActionEvent e)
+          throws IOException, InterruptedException
   {
 
   }
index 9f98ffa..ca11541 100755 (executable)
@@ -34,6 +34,7 @@ import jalview.io.BackupFiles;
 import jalview.io.BackupFilesPresetEntry;
 import jalview.io.IntKeyStringValueEntry;
 import jalview.util.MessageManager;
+import jalview.util.Platform;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -48,7 +49,6 @@ 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.KeyListener;
 import java.awt.event.MouseAdapter;
@@ -56,13 +56,16 @@ import java.awt.event.MouseEvent;
 import java.util.Arrays;
 import java.util.List;
 
+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;
@@ -86,6 +89,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.
  * 
@@ -160,10 +165,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
    */
@@ -283,6 +293,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;
+
+  /*
    * Web Services tab
    */
   protected JPanel wsTab = new JPanel();
@@ -387,6 +414,8 @@ public class GPreferences extends JPanel
     tabbedPane.add(initEditingTab(),
             MessageManager.getString("label.editing"));
 
+    tabbedPane.add(initHMMERTab(), MessageManager.getString("label.hmmer"));
+
     /*
      * See WsPreferences for the real work of configuring this tab.
      */
@@ -395,7 +424,7 @@ public class GPreferences extends JPanel
 
     /*
      * Handler to validate a tab before leaving it - currently only for
-     * Structure.
+     * Structure
      */
     tabbedPane.addChangeListener(new ChangeListener()
     {
@@ -449,6 +478,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
@@ -1006,7 +1163,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);
@@ -1018,7 +1175,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);
@@ -1027,11 +1184,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);
@@ -1282,7 +1439,7 @@ public class GPreferences extends JPanel
       {
         if (e.getClickCount() == 2)
         {
-          String chosen = openFileChooser();
+          String chosen = openFileChooser(false);
           if (chosen != null)
           {
             chimeraPath.setText(chosen);
@@ -1337,10 +1494,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(
@@ -1356,21 +1517,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;
@@ -2832,5 +2978,41 @@ 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 2d8a4a6..aaf8519 100644 (file)
@@ -41,6 +41,7 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.GeneLocus;
 import jalview.datamodel.GraphLine;
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.PDBEntry;
 import jalview.datamodel.Point;
 import jalview.datamodel.RnaViewerModel;
@@ -72,6 +73,7 @@ import jalview.gui.TreePanel;
 import jalview.io.BackupFiles;
 import jalview.io.DataSourceType;
 import jalview.io.FileFormat;
+import jalview.io.HMMFile;
 import jalview.io.NewickFile;
 import jalview.math.Matrix;
 import jalview.math.MatrixI;
@@ -214,6 +216,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";
 
   /**
@@ -1052,6 +1056,9 @@ public class Jalview2XML
         jseq.getFeatures().add(features);
       }
 
+      /*
+       * save PDB entries for sequence
+       */
       if (jdatasq.getAllPDBEntries() != null)
       {
         Enumeration<PDBEntry> en = jdatasq.getAllPDBEntries().elements();
@@ -1144,6 +1151,11 @@ public class Jalview2XML
 
       saveRnaViewers(jout, jseq, jds, viewIds, ap, storeDS);
 
+      if (jds.hasHMMProfile())
+      {
+        saveHmmerProfile(jout, jseq, jds);
+      }
+
       // jms.addJSeq(jseq);
       object.getJSeq().add(jseq);
     }
@@ -1691,7 +1703,39 @@ public class Jalview2XML
     }
     return object;
   }
+  /**
+   * 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());
+    }
+  }
 
+    
   /**
    * Writes PCA viewer attributes and computed values to an XML model object and
    * adds it to the JalviewModel. Any exceptions are reported by logging.
@@ -2085,9 +2129,9 @@ 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());
+         Cache.log.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
@@ -3586,6 +3630,18 @@ public class Jalview2XML
             }
           }
         }
+
+        /*
+         * load any HMMER profile
+         */
+        // TODO fix this
+
+        String hmmJarFile = jseqs.get(i).getHmmerProfile();
+        if (hmmJarFile != null && jprovider != null)
+        {
+          loadHmmerProfile(jprovider, hmmJarFile, al.getSequenceAt(i));
+        }
+
       }
     } // end !multipleview
 
@@ -4060,6 +4116,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.
@@ -5447,10 +5528,10 @@ public class Jalview2XML
     String id = object.getViewport().get(0).getSequenceSetId();
     if (skipList.containsKey(id))
     {
-      if (Cache.log != null && Cache.log.isDebugEnabled())
-      {
-        Cache.log.debug("Skipping seuqence set id " + id);
-      }
+       if (Cache.log != null && Cache.log.isDebugEnabled())
+        {
+          Cache.log.debug("Skipping seuqence set id " + id);
+        }
       return true;
     }
     return false;
@@ -5924,7 +6005,6 @@ public class Jalview2XML
         jmap.setTo(djs);
         incompleteSeqs.put(sqid, djs);
         seqRefIds.put(sqid, djs);
-
       }
       jalview.bin.Cache.log.debug("about to recurse on addDBRefs.");
       addDBRefs(djs, ms);
@@ -6108,7 +6188,7 @@ public class Jalview2XML
       }
       else
       {
-        Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
+          Cache.log.debug("Ignoring " + jvobj.getClass() + " (ID = " + id);
       }
     }
   }
@@ -6582,7 +6662,7 @@ 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);
+          Cache.log.warn("Couldn't parse out graduated feature color.", e);
       }
   
       NoValueColour noCol = colourModel.getNoValueColour();
index adca17e..40fb513 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
    */
@@ -345,8 +355,12 @@ public class AnnotationRenderer
     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.getIgnoreGapsConsensus());
       }
       // 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 75a07b9..a84ea52 100755 (executable)
@@ -37,6 +37,16 @@ import java.util.Map;
 
 public class AnnotationColourGradient extends FollowerColourScheme
 {
+  /**
+   * map positional scores to transparency rather than colour
+   */
+  boolean positionToTransparency = true;
+
+  /**
+   * compute shade based on annotation row score
+   */
+  boolean perLineScore = true;
+
   public static final int NO_THRESHOLD = -1;
 
   public static final int BELOW_THRESHOLD = 0;
@@ -94,6 +104,8 @@ public class AnnotationColourGradient extends FollowerColourScheme
     acg.predefinedColours = predefinedColours;
     acg.seqAssociated = seqAssociated;
     acg.noGradient = noGradient;
+    acg.positionToTransparency = positionToTransparency;
+    acg.perLineScore = perLineScore;
     return acg;
   }
 
@@ -192,14 +204,16 @@ public class AnnotationColourGradient extends FollowerColourScheme
       AnnotatedCollectionI alcontext = alignment instanceof AlignmentI
               ? alignment
               : alignment.getContext();
-      boolean f = true, rna = false;
-      for (AlignmentAnnotation alan : alcontext
-              .findAnnotation(annotation.getCalcId()))
+      boolean f = true, sf = true, rna = false;
+      long plcount = 0, ancount = 0;
+      for (AlignmentAnnotation alan : alcontext.findAnnotation(annotation
+              .getCalcId()))
       {
         if (alan.sequenceRef != null
                 && (alan.label != null && annotation != null
                         && alan.label.equals(annotation.label)))
         {
+          ancount++;
           if (!rna && alan.isRNA())
           {
             rna = true;
@@ -214,8 +228,30 @@ public class AnnotationColourGradient extends FollowerColourScheme
             aamin = alan.graphMin;
           }
           f = false;
+          if (alan.score == alan.score)
+          {
+            if (sf || alan.score < plmin)
+            {
+              plmin = alan.score;
+            }
+            if (sf || alan.score > plmax)
+            {
+              plmax = alan.score;
+            }
+            sf = false;
+            plcount++;
+          }
         }
       }
+      if (plcount > 0 && plcount == ancount)
+      {
+        perLineScore = plcount == ancount;
+        aamax=plmax;
+      }
+      else
+      {
+        perLineScore = false;
+      }
       if (rna)
       {
         ColourSchemeProperty.initRnaHelicesShading(1 + (int) aamax);
@@ -223,7 +259,15 @@ public class AnnotationColourGradient extends FollowerColourScheme
     }
   }
 
-  float aamin = 0f, aamax = 0f;
+  /**
+   * positional annotation max/min
+   */
+  double aamin = 0.0, aamax = 0.0;
+
+  /**
+   * per line score max/min
+   */
+  double plmin = Double.NaN, plmax = Double.NaN;
 
   public AlignmentAnnotation getAnnotation()
   {
@@ -439,11 +483,25 @@ public class AnnotationColourGradient extends FollowerColourScheme
       }
     }
 
-    int dr = (int) (redRange * range + redMin);
-    int dg = (int) (greenRange * range + greenMin);
-    int db = (int) (blueRange * range + blueMin);
-
-    return new Color(dr, dg, db);
+    // midtr sets the ceiling for bleaching out the shading
+    int trans = 0, midtr = 239;
+    if (perLineScore)
+    {
+      trans = (int) ((1f - range) * midtr);
+      range = (float) ((ann.score - plmin) / (plmax - aamin));
+    }
+    int dr = (int) (redRange * range + redMin),
+            dg = (int) (greenRange * range + greenMin),
+            db = (int) (blueRange * range + blueMin);
+    if (ann.score == ann.score && positionToTransparency)
+    {
+      return new Color(Math.min(dr + trans, midtr), Math.min(dg
+              + trans, midtr), Math.min(db + trans, midtr));
+    }
+    else
+    {
+      return new Color(dr, dg, db);
+    }
   }
 
   public boolean isPredefinedColours()
diff --git a/src/jalview/schemes/HMMMatchScoreColourScheme.java b/src/jalview/schemes/HMMMatchScoreColourScheme.java
new file mode 100644 (file)
index 0000000..96eb26a
--- /dev/null
@@ -0,0 +1,369 @@
+package jalview.schemes;
+
+import jalview.api.AlignViewportI;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceI;
+import jalview.util.ColorUtils;
+import jalview.util.Comparison;
+
+import java.awt.Color;
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+
+
+public class HMMMatchScoreColourScheme extends ResidueColourScheme
+{
+  
+  private Map<Character, Map<Integer, Map<String, Double>>> probabilities;
+
+  private List<Integer> ranges;
+
+  private static double binSize;
+
+  public class MatchProbReader
+  {
+    private BufferedReader reader;
+    
+    MatchProbReader() throws FileNotFoundException
+    {
+      reader = new BufferedReader(
+              new FileReader("resources/ProbabilityOfMatch"));
+    }
+    
+    /*
+    public Map<Character, Map<String, Double>>  getProbabilities() throws IOException
+    {
+      Map<Character, Map<String, Double>> probabilities = new HashMap<>();
+      
+      String[] alphabet = reader.readLine().split("\\,");
+      for (int i = 1; i < alphabet.length - 1; i++)
+      {
+        probabilities.put(alphabet[i].replaceAll("\\ ", "").charAt(0),
+                new HashMap<>());
+      }
+      
+      String line = reader.readLine();
+      while(line != null)
+      {
+        String[] contents = line.split("\\,");
+        
+        for(int i = 1; i < contents.length; i++)
+        {
+          probabilities.get(alphabet[i].replaceAll("\\ ", "").charAt(0))
+                  .put(contents[0], Double
+                          .valueOf(contents[i].replaceAll("\\ ", "")));
+        }
+        line = reader.readLine();
+    
+      }
+      reader.close();
+      return probabilities;
+    }
+    */
+    
+    public Map<Character, Map<Integer, Map<String, Double>>> getProbabilities()
+            throws IOException
+    {
+
+      Map<Character, Map<Integer, Map<String, Double>>> probabilities = new HashMap<>();
+
+      ranges = new ArrayList<>();
+      ranges.add(0);
+
+      binSize = Double.valueOf((reader.readLine().replaceAll("\\ ", "")));
+      String line = reader.readLine();
+      char c = line.charAt(0);
+
+      while (line != null)
+      {
+        line = reader.readLine();
+        while (line != null && line.split("\\,").length != 1)
+        {
+          String[] llrs = line.split("\\,");
+          String[] counts = reader.readLine().split("\\,");
+          int range = Integer.valueOf(llrs[0]);
+
+          if (!ranges.contains(range))
+          {
+            ranges.add(range);
+          }
+          if (!probabilities.containsKey(c))
+          {
+            probabilities.put(c, new HashMap<>());
+          }
+          probabilities.get(c).put(range, new HashMap<>());
+
+          for (int i = 1; i < llrs.length; i++)
+          {
+            probabilities.get(c).get(range).put(
+                    llrs[i].replaceAll("\\ ", ""),
+                    Double.valueOf(counts[i].replaceAll("\\ ", "")));
+          }
+
+          line = reader.readLine();
+        }
+        if (line != null)
+        {
+          c = line.charAt(0);
+        }
+      }
+
+      return probabilities;
+    }
+    
+  }
+
+  private static final Color INSERTION_COLOUR = Color.white;
+
+  /*
+   * 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
+   * @throws IOException
+   */
+  public HMMMatchScoreColourScheme(List<SequenceI> hmmSeqs)
+  {
+    hmmSeq = hmmSeqs.isEmpty() ? null : hmmSeqs.get(0);
+    hmm = hmmSeq == null ? null : hmmSeq.getHMM();
+
+    try
+    {
+      MatchProbReader probabilityReader = new MatchProbReader();
+      probabilities = probabilityReader.getProbabilities();
+    } catch (IOException e)
+    {
+      System.out.println(e.getStackTrace());
+    }
+  }
+
+  /**
+   * Default constructor (required by ColourSchemes.loadColourSchemes)
+   */
+  public HMMMatchScoreColourScheme()
+  {
+  }
+
+  @Override
+  public Color findColour(char symbol, int column, SequenceI seq,
+          String consensusResidue, float pid)
+  {
+    if (seq == null)
+    {
+      return null;
+    }
+    return findColour(symbol, column, seq.gapMap().length);
+  }
+
+  // TODO change documentation
+  /**
+   * 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, int length)
+  {
+    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);
+    }
+
+    double prob = 0;
+    if (hmm.getBackgroundFrequencies().containsKey(symbol))
+    {
+      int lengthBin = getLengthBin(length);
+
+      double llr = Math
+              .log(getHmm().getMatchEmissionProbability(column, symbol)
+                      / hmm.getBackgroundFrequencies().get(symbol));
+
+      if (!probabilities.containsKey(symbol)
+              || !probabilities.get(symbol).get(lengthBin)
+              .containsKey(format(llr)))
+      {
+        return new Color(140, 140, 140);
+      }
+
+
+      prob = probabilities.get(symbol).get(lengthBin).get(format(llr));
+    }
+    else
+    {
+      return new Color(140, 140, 140);
+    }
+
+    Color colour = Color.ORANGE;
+    if (prob >= 0.5)
+    {
+
+      colour = ColorUtils.getGraduatedColour((float) prob, 0.5f,
+              Color.WHITE, 1f,
+              Color.blue);
+    }
+    else
+    {
+      colour = ColorUtils.getGraduatedColour((float) prob, 0f, Color.red,
+              0.5f, Color.WHITE);
+    }
+
+    return colour;
+  }
+
+  public static String format(Double d)
+  {
+    String formatArg = String.valueOf(binSize);
+
+    // if bin size, need format "%.n" where n is number of decimal places
+    if (binSize < 1)
+    {
+      formatArg = "." + formatArg.split("\\.")[1].length();
+    }
+
+    Double rounded = Math.round(d / binSize) * binSize;
+    String formatted = String.format("%" + formatArg + "f", rounded);
+
+    // format sometimes returns a number rounded to 0 as -0
+    // this ensures output will always be 0
+    if (Double.valueOf(formatted) == 0)
+    {
+      formatted = "0";
+    }
+    return formatted;
+
+  }
+
+  /**
+   * Answers the maximum possible value of information score (log ratio), for use
+   * in scaling a graduated colour range
+   * 
+   * @return
+   */
+  protected float getMaxInformationScore()
+  {
+    return 0f;
+  }
+
+  /**
+   * Answers a new colour scheme instance based on the HMM of the first sequence
+   * in ac that has an HMM
+   */
+  @Override
+  public ColourSchemeI getInstance(AlignViewportI viewport,
+          AnnotatedCollectionI ac)
+  {
+    return newInstance(ac);
+  }
+
+  /**
+   * Constructor given a sequence collection
+   * 
+   * @param ac
+   */
+  public HMMMatchScoreColourScheme(AnnotatedCollectionI ac)
+  {
+    this(ac.getHmmSequences());
+  }
+
+  /**
+   * Answers a new instance of the colour scheme for the given HMM
+   * 
+   * @param ac
+   * @return
+   */
+  protected HMMMatchScoreColourScheme newInstance(AnnotatedCollectionI ac)
+  {
+    return new HMMMatchScoreColourScheme(ac);
+  }
+
+  @Override
+  public boolean isSimple()
+  {
+    return false;
+  }
+
+  /**
+   * Answers true if the sequence collection has an HMM consensus sequence and
+   * that the first HMM sequence contains background frequencies, else false
+   */
+  @Override
+  public boolean isApplicableTo(AnnotatedCollectionI ac)
+  {
+    return !ac.getHmmSequences().isEmpty() && ac.getHmmSequences().get(0)
+            .getHMM().getBackgroundFrequencies() != null;
+  }
+
+  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;
+  }
+
+  @Override
+  public String getSchemeName()
+  {
+    return JalviewColourScheme.HMMMatchScore.toString();
+  }
+
+  private int getLengthBin(int l)
+  {
+    for (int i = 1; i < ranges.size(); i++)
+    {
+      if (l >= ranges.get(i - 1) && l < ranges.get(i))
+      {
+        return ranges.get(i);
+      }
+    }
+    return -1;
+  }
+}
+
+
diff --git a/src/jalview/schemes/HmmerColourScheme.java b/src/jalview/schemes/HmmerColourScheme.java
new file mode 100644 (file)
index 0000000..05c9b66
--- /dev/null
@@ -0,0 +1,197 @@
+package jalview.schemes;
+
+import jalview.api.AlignViewportI;
+import jalview.datamodel.AnnotatedCollectionI;
+import jalview.datamodel.HiddenMarkovModel;
+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(AlignViewportI viewport,
+          AnnotatedCollectionI ac)
+  {
+    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..a24b7ab
--- /dev/null
@@ -0,0 +1,73 @@
+package jalview.schemes;
+
+import jalview.api.AlignViewportI;
+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;
+  }
+
+  /**
+   * Answers a new colour scheme instance based on the HMM of the first sequence
+   * in alignment that has an HMM
+   */
+  @Override
+  public ColourSchemeI getInstance(AlignViewportI viewport,
+          AnnotatedCollectionI ac)
+  {
+    return newInstance(ac);
+  }
+
+}
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 456397e..eb1edf1 100644 (file)
@@ -43,7 +43,10 @@ public enum JalviewColourScheme
   PurinePyrimidine("Purine/Pyrimidine", PurinePyrimidineColourScheme.class),
   RNAHelices("RNA Helices", RNAHelicesColour.class),
   TCoffee("T-Coffee Scores", TCoffeeColourScheme.class),
-  IdColour("Sequence ID", IdColourScheme.class);
+  IdColour("Sequence ID", IdColourScheme.class),
+  HMMERU("HMMER-Uniprot", HmmerGlobalBackground.class),
+  HMMERA("HMMER-Alignment", HmmerLocalBackground.class),
+  HMMMatchScore("HMM Match Score", HMMMatchScoreColourScheme.class);
   // RNAInteraction("RNA Interaction type", RNAInteractionColourScheme.class)
 
   private String name;
index d435065..087c16a 100755 (executable)
@@ -34,6 +34,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
 
@@ -50,6 +57,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];
@@ -2270,6 +2280,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);
index d4fc233..4afa12d 100644 (file)
@@ -256,7 +256,7 @@ public class Comparison
    */
   public static final boolean isGap(char c)
   {
-    return (c == GAP_DASH || c == GAP_DOT || c == GAP_SPACE) ? true : false;
+    return (c == GAP_DASH || c == GAP_DOT || c == GAP_SPACE);
   }
 
   /**
diff --git a/src/jalview/util/FileUtils.java b/src/jalview/util/FileUtils.java
new file mode 100644 (file)
index 0000000..7e607ab
--- /dev/null
@@ -0,0 +1,208 @@
+package jalview.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.PathMatcher;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 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;
+  }
+
+  /**
+   * Answers a (possibly empty) list of file paths found by searching below
+   * <code>from</code> that match the supplied regular expression
+   * <code>pattern</code>. Results may include <code>from</code> itself if it
+   * matches. If an exception occurs it is written to syserr and any results up to
+   * that point are returned. Note that the regular expression match applies to
+   * the whole path of any matched file.
+   * <p>
+   * WARNING: because the whole directory tree below <code>from</code> is
+   * searched, this method may be slow if used for a high level directory, or may
+   * exit prematurely if security or other exceptions occur.
+   * 
+   * <pre>
+   * Example: 
+   *   findMatchingPaths(Paths.get("C:/Program Files"), ".*&#47chimera.exe$")
+   * </pre>
+   * 
+   * @param from
+   * @param pattern
+   * 
+   * @return
+   * @see https://stackoverflow.com/questions/794381/how-to-find-files-that-match-a-wildcard-string-in-java/31685610#comment62441832_31685610
+   */
+  public static List<String> findMatchingPaths(Path from, String pattern)
+  {
+    List<String> matches = new ArrayList<>();
+    PathMatcher pathMatcher = FileSystems.getDefault()
+            .getPathMatcher("regex:" + pattern);
+    try
+    {
+      Files.walk(from).filter(pathMatcher::matches)
+              .forEach(m -> matches.add(m.toString()));
+    } catch (IOException e)
+    {
+      System.err.println(
+              "Error searching for " + pattern + " : " + e.toString());
+    }
+
+    return matches;
+  }
+
+  /**
+   * Answers a (possibly empty) list of paths to files below the given root path,
+   * that match the given pattern. The pattern should be a '/' delimited set of
+   * glob patterns, each of which is used to match child file names (not full
+   * paths). Note that 'directory spanning' glob patterns (**) are <em>not</em>
+   * supported by this method.
+   * <p>
+   * For example
+   * 
+   * <pre>
+   *   findMatches("C:\\", "Program Files*&#47Chimera*&#47bin/{chimera,chimera.exe}"
+   * </pre>
+   * 
+   * would match "C:\Program Files\Chimera 1.11\bin\chimera.exe" and "C:\Program
+   * Files (x86)\Chimera 1.10.1\bin\chimera"
+   * 
+   * @param root
+   * @param pattern
+   * @return
+   * @see https://docs.oracle.com/javase/tutorial/essential/io/fileOps.html#glob
+   */
+  public static List<String> findMatches(String root, String pattern)
+  {
+    List<String> results = new ArrayList<>();
+    try
+    {
+      Path from = Paths.get(root);
+      findMatches(results, from, Arrays.asList(pattern.split("/")));
+    } catch (Throwable e)
+    {
+      // Paths.get can throw IllegalArgumentException
+      System.err.println(String.format("Error searching %s for %s: %s",
+              root, pattern, e.toString()));
+    }
+
+    return results;
+  }
+
+  /**
+   * A helper method that performs recursive search of file patterns and adds any
+   * 'leaf node' matches to the results list
+   * 
+   * @param results
+   * @param from
+   * @param patterns
+   */
+  protected static void findMatches(List<String> results, Path from,
+          List<String> patterns)
+  {
+    if (patterns.isEmpty())
+    {
+      /*
+       * reached end of recursion with all components matched
+       */
+      results.add(from.toString());
+      return;
+    }
+
+    String pattern = patterns.get(0);
+    try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(from,
+            pattern))
+    {
+      dirStream.forEach(p -> {
+
+        /*
+         * matched a next level file - search below it
+         * (ignore non-directory non-leaf matches)
+         */
+        List<String> subList = patterns.subList(1, patterns.size());
+        if (subList.isEmpty() || p.toFile().isDirectory())
+        {
+          findMatches(results, p, subList);
+        }
+      });
+    } catch (IOException e)
+    {
+      System.err.println(String.format("Error searching %s: %s", pattern,
+              e.toString()));
+    }
+  }
+}
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 a5a9460..97c84bc 100644 (file)
@@ -20,6 +20,9 @@
  */
 package jalview.util;
 
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
@@ -64,4 +67,46 @@ public class HttpUtils
     return false;
   }
 
+  /**
+   * download from given URL and return a pointer to temporary file
+   */
+  public static File fetchURLToTemp(String url) throws OutOfMemoryError,
+          IOException
+  {
+    long time = System.currentTimeMillis();
+    URL rcall = new URL(url);
+
+    InputStream is = new BufferedInputStream(rcall.openStream());
+    File outFile = null;
+    try
+    {
+      outFile = File.createTempFile("jalview", ".xml");
+      outFile.deleteOnExit();
+      if (outFile.length() == 0)
+      {
+        outFile.delete();
+        return null;
+      }
+    } catch (Exception ex)
+    {
+    }
+
+    if (outFile != null)
+    {
+      FileOutputStream fio = new FileOutputStream(outFile);
+      byte[] bb = new byte[32 * 1024];
+      int l;
+      while ((l = is.read(bb)) > 0)
+      {
+        fio.write(bb, 0, l);
+      }
+      fio.close();
+      is.close();
+      return outFile;
+    }
+    else
+    {
+      return null;
+    }
+  }
 }
index 731e976..986b18c 100644 (file)
@@ -1044,70 +1044,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 e8558fa..0dae54e 100644 (file)
@@ -50,7 +50,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 2e8ace8..3c5ba92 100644 (file)
@@ -107,29 +107,6 @@ public class StringUtils
   }
 
   /**
-   * Returns the last part of 'input' after the last occurrence of 'token'. For
-   * example to extract only the filename from a full path or URL.
-   * 
-   * @param input
-   * @param token
-   *          a delimiter which must be in regular expression format
-   * @return
-   */
-  public static String getLastToken(String input, String token)
-  {
-    if (input == null)
-    {
-      return null;
-    }
-    if (token == null)
-    {
-      return input;
-    }
-    String[] st = input.split(token);
-    return st[st.length - 1];
-  }
-
-  /**
    * Parses the input string into components separated by the delimiter. Unlike
    * String.split(), this method will ignore occurrences of the delimiter which
    * are nested within single quotes in name-value pair values, e.g. a='b,c'.
@@ -146,7 +123,7 @@ public class StringUtils
     {
       return null;
     }
-    List<String> jv = new ArrayList<String>();
+    List<String> jv = new ArrayList<>();
     int cp = 0, pos, escape;
     boolean wasescaped = false, wasquoted = false;
     String lstitem = null;
index 8dcd1b3..a9334ff 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;
@@ -101,6 +102,27 @@ public abstract class AlignmentViewport
    * alignment displayed in the viewport. Please use get/setter
    */
   protected AlignmentI alignment;
+  
+  /*
+   * probably unused indicator that view is of a dataset rather than an
+   * alignment
+   */
+
+  protected boolean ignoreBelowBackGroundFrequencyCalculation = false;
+
+  protected boolean infoLetterHeight = false;
+
+  protected AlignmentAnnotation occupancy;
+  
+  /**
+   * results of alignment consensus analysis for visible portion of view
+   */
+  protected ProfilesI consensusProfiles;
+
+  /**
+   * HMM profile for the alignment
+   */
+  protected ProfilesI hmmProfiles;
 
   public AlignmentViewport(AlignmentI al)
   {
@@ -588,7 +610,7 @@ public abstract class AlignmentViewport
    * alignment
    */
   protected boolean isDataset = false;
-
+  
   public void setDataset(boolean b)
   {
     isDataset = b;
@@ -610,7 +632,7 @@ public abstract class AlignmentViewport
   protected boolean ignoreGapsInConsensusCalculation = false;
 
   protected ResidueShaderI residueShading = new ResidueShader();
-
+  
   @Override
   public void setGlobalColourScheme(ColourSchemeI cs)
   {
@@ -684,7 +706,7 @@ public abstract class AlignmentViewport
   {
     return residueShading;
   }
-
+  
   protected AlignmentAnnotation consensus;
 
   protected AlignmentAnnotation complementConsensus;
@@ -718,7 +740,7 @@ public abstract class AlignmentViewport
   protected Hashtable[] hStrucConsensus = null;
 
   protected Conservation hconservation = null;
-
+  
   @Override
   public void setConservation(Conservation cons)
   {
@@ -756,6 +778,18 @@ public abstract class AlignmentViewport
   }
 
   @Override
+  public void setHmmProfiles(ProfilesI info)
+  {
+    hmmProfiles = info;
+  }
+
+  @Override
+  public ProfilesI getHmmProfiles()
+  {
+    return hmmProfiles;
+  }
+
+  @Override
   public Hashtable[] getComplementConsensusHash()
   {
     return hcomplementConsensus;
@@ -884,6 +918,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)
   {
@@ -947,6 +991,7 @@ public abstract class AlignmentViewport
     strucConsensus = null;
     conservation = null;
     quality = null;
+    consensusProfiles = null;
     groupConsensus = null;
     groupConservation = null;
     hconsensus = null;
@@ -1002,6 +1047,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
@@ -1011,6 +1071,15 @@ public abstract class AlignmentViewport
   }
 
   /**
+   * @return the showInformationProfile
+   */
+  @Override
+  public boolean isShowHMMSequenceLogo()
+  {
+    return hmmShowSequenceLogo;
+  }
+
+  /**
    * @param showSequenceLogo
    *          the new value
    */
@@ -1028,6 +1097,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
@@ -1038,6 +1119,14 @@ public abstract class AlignmentViewport
   }
 
   /**
+   * @param showInformationHistogram
+   */
+  public void setShowInformationHistogram(boolean showInformationHistogram)
+  {
+    this.hmmShowHistogram = showInformationHistogram;
+  }
+
+  /**
    * @return the showGroupConservation
    */
   public boolean isShowGroupConservation()
@@ -1083,6 +1172,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;
@@ -1238,7 +1338,16 @@ public abstract class AlignmentViewport
                 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;
@@ -1295,6 +1404,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(
@@ -1889,7 +2010,6 @@ public abstract class AlignmentViewport
 
     updateAllColourSchemes();
     calculator.restartWorkers();
-    // alignment.adjustSequenceAnnotations();
   }
 
   /**
@@ -1942,6 +2062,7 @@ public abstract class AlignmentViewport
               MessageManager.getString("label.consensus_descr"),
               new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
       initConsensus(consensus);
+
       initGapCounts();
 
       initComplementConsensus();
@@ -2148,6 +2269,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
@@ -2185,6 +2309,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)
         {
@@ -2969,6 +3096,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)
   {
@@ -2981,6 +3121,28 @@ 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;
+  }
+
   /**
    * flag set to indicate if structure views might be out of sync with sequences
    * in the alignment
@@ -3044,4 +3206,46 @@ public abstract class AlignmentViewport
       codingComplement.setUpdateStructures(needToUpdateStructureViews);
     }
   }
+
+  /**
+   * Filters out sequences with an eValue higher than the specified value. The
+   * filtered sequences are hidden or deleted. Sequences with no eValues are also
+   * filtered out.
+   * 
+   * @param eValue
+   * @param delete
+   */
+  public void filterByEvalue(double eValue)
+  {
+    for (SequenceI seq : alignment.getSequencesArray())
+    {
+      if ((seq.getAnnotation("Search Scores") == null
+              || seq.getAnnotation("Search Scores")[0].getEValue() > eValue)
+              && seq.getHMM() == null)
+      {
+        hideSequence(new SequenceI[] { seq });
+      }
+    }
+  }
+
+  /**
+   * Filters out sequences with an score lower than the specified value. The
+   * filtered sequences are hidden or deleted.
+   * 
+   * @param score
+   * @param delete
+   */
+  public void filterByScore(double score)
+  {
+    for (SequenceI seq : alignment.getSequencesArray())
+    {
+      if ((seq.getAnnotation("Search Scores") == null
+              || seq.getAnnotation("Search Scores")[0]
+                      .getBitScore() < score)
+              && seq.getHMM() == null)
+      {
+        hideSequence(new SequenceI[] { seq });
+      }
+    }
+  }
 }
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 78c6da2..c98c27d 100644 (file)
@@ -222,7 +222,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,
diff --git a/src/jalview/workers/InformationThread.java b/src/jalview/workers/InformationThread.java
new file mode 100644 (file)
index 0000000..85cd92f
--- /dev/null
@@ -0,0 +1,323 @@
+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.getAlignmentGapAnnotation();
+  }
+
+  /**
+   * 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();
+      if (!hmmSeqs.isEmpty())
+      {
+        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 f5f9377..4a9cb74 100644 (file)
  */
 package jalview.ws;
 
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.WsParamSetI;
+
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
 /**
  * Generic properties for an individual job within a Web Service Client thread.
  * Derived from jalview web services version 1 statuses, and revised for Jws2.
@@ -145,6 +152,12 @@ public abstract class AWsJob
    */
   protected boolean subjobComplete = false;
 
+  protected WsParamSetI preset = null;
+
+  protected List<ArgumentI> arguments = null;
+
+  protected Hashtable<String, Map> SeqNames = new Hashtable();
+
   public AWsJob()
   {
   }
@@ -227,4 +240,47 @@ public abstract class AWsJob
     String state = "";
     return state;
   }
+
+  public void setPreset(WsParamSetI jobpreset)
+  {
+    preset = jobpreset;
+  }
+
+  public void setArguments(List<ArgumentI> paramset)
+  {
+    arguments = paramset;
+
+  }
+
+  public boolean isPresetJob()
+  {
+    return preset!=null && arguments==null; 
+  }
+
+  public List<ArgumentI> getArguments()
+  {
+    return arguments;
+  }
+
+  public WsParamSetI getPreset()
+  {
+    return preset;
+  }
+
+  long nextChunk = 0;
+
+  /**
+   * update the record of the last position in the log file read for this job
+   * 
+   * @param nextChunk
+   */
+  public void setnextChunk(long nextChunk)
+  {
+    this.nextChunk = nextChunk;
+  }
+
+  public long getNextChunk()
+  {
+    return nextChunk;
+  }
 }
index 0f5cee8..33aea90 100755 (executable)
  */
 package jalview.ws;
 
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
 import jalview.gui.WebserviceInfo;
+import jalview.gui.WsJobParameters;
+import jalview.util.MessageManager;
+import jalview.ws.api.ServiceWithParameters;
+import jalview.ws.api.UIinfo;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.ParamDatastoreI;
+import jalview.ws.params.WsParamSetI;
+
+import java.util.List;
 
 public abstract class WSClient // implements WSMenuEntryProviderI
 {
@@ -56,6 +67,11 @@ public abstract class WSClient // implements WSMenuEntryProviderI
   protected WebserviceInfo wsInfo;
 
   /**
+   * the root object for the service client
+   */
+  protected UIinfo serviceHandle;
+
+  /**
    * total number of jobs managed by this web service client instance.
    */
   int jobsRunning = 0;
@@ -65,13 +81,119 @@ public abstract class WSClient // implements WSMenuEntryProviderI
    * mappings between abstract interface names and menu entries
    */
   protected java.util.Hashtable ServiceActions;
+
+  /**
+   * alignFrame associated with this client
+   */
+  protected AlignFrame alignFrame;
   {
     ServiceActions = new java.util.Hashtable();
     ServiceActions.put("MsaWS", "Multiple Sequence Alignment");
     ServiceActions.put("SecStrPred", "Secondary Structure Prediction");
   };
 
+  /**
+   * The preset for the job executed by this client (may be null)
+   */
+  protected WsParamSetI preset;
+
+  /**
+   * The parameters for the job executed by this client (may be null)
+   */
+  protected List<ArgumentI> paramset;
+
   public WSClient()
   {
   }
+
+  /**
+   * base constructor for a web service with parameters. Extending classes
+   * should implement this constructor with additional logic to verify that
+   * preset and arguments are compatible with the service being configured.
+   * 
+   * @param _alignFrame
+   * @param preset
+   * @param arguments
+   */
+  public WSClient(AlignFrame _alignFrame, WsParamSetI preset,
+          List<ArgumentI> arguments)
+  {
+    alignFrame = _alignFrame;
+    this.preset = preset;
+    this.paramset = arguments;
+  }
+
+  protected WebserviceInfo setWebService(UIinfo serv, boolean b)
+  {
+    WebServiceName = serv.getName();
+    WebServiceJobTitle = serv.getActionText();
+    WsURL = serv.getHostURL();
+    if (!b)
+    {
+      return new WebserviceInfo(WebServiceJobTitle,
+              WebServiceJobTitle + " using service hosted at "
+                      + WsURL + "\n"
+                      + (serv.getDescription() != null
+                              ? serv.getDescription()
+                              : ""),
+              false);
+    }
+    return null;
+  }
+
+  /**
+   * called to open a parameter editing dialog for parameterised services
+   * 
+   * @param sh
+   * @param editParams
+   * @return
+   */
+  protected boolean processParams(ServiceWithParameters sh,
+          boolean editParams)
+  {
+    return processParams(sh, editParams, false);
+  }
+
+  protected boolean processParams(ServiceWithParameters sh,
+          boolean editParams,
+          boolean adjustingExisting)
+  {
+
+    if (editParams)
+    {
+      // always do this
+      sh.initParamStore(Desktop.getUserParameterStore());
+
+      WsJobParameters jobParams = (preset == null && paramset != null
+              && paramset.size() > 0)
+                      ? new WsJobParameters((ParamDatastoreI) null, sh,
+                              (WsParamSetI) null, paramset)
+                      : new WsJobParameters((ParamDatastoreI) null, sh,
+                              preset, (List<ArgumentI>) null);
+      if (adjustingExisting)
+      {
+        jobParams.setName(MessageManager
+                .getString("label.adjusting_parameters_for_calculation"));
+      }
+      if (!jobParams.showRunDialog())
+      {
+        return false; // dialog cancelled
+      }
+
+      WsParamSetI prset = jobParams.getPreset();
+      if (prset == null)
+      {
+        paramset = jobParams.isServiceDefaults() ? null
+                : jobParams.getJobParams();
+        this.preset = null;
+      }
+      else
+      {
+        this.preset = prset; // ((JabaPreset) prset).p;
+        paramset = null; // no user supplied parameters.
+      }
+    }
+    return true;
+  }
+
 }
diff --git a/src/jalview/ws/api/CancellableI.java b/src/jalview/ws/api/CancellableI.java
new file mode 100644 (file)
index 0000000..adef2b9
--- /dev/null
@@ -0,0 +1,8 @@
+package jalview.ws.api;
+
+import jalview.ws.gui.WsJob;
+
+public interface CancellableI
+{
+  public boolean cancel(WsJob job);
+}
diff --git a/src/jalview/ws/api/DistanceMatrixResultI.java b/src/jalview/ws/api/DistanceMatrixResultI.java
new file mode 100644 (file)
index 0000000..a40d256
--- /dev/null
@@ -0,0 +1,16 @@
+package jalview.ws.api;
+
+import jalview.math.MatrixI;
+import jalview.ws.params.InvalidArgumentException;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+
+public interface DistanceMatrixResultI
+{
+
+  public MatrixI getDistanceMatrixFor(JobId jobId)
+          throws InvalidArgumentException, ServerError, IOError;
+
+
+}
\ No newline at end of file
diff --git a/src/jalview/ws/api/JalviewServiceEndpointProviderI.java b/src/jalview/ws/api/JalviewServiceEndpointProviderI.java
new file mode 100644 (file)
index 0000000..b9b5109
--- /dev/null
@@ -0,0 +1,13 @@
+package jalview.ws.api;
+
+public interface JalviewServiceEndpointProviderI
+{
+
+  /**
+   * 
+   * @return endpoint instance implementing one or more jalview.ws.api
+   *         interfaces
+   */
+  Object getEndpoint();
+
+}
diff --git a/src/jalview/ws/api/JalviewWebServiceI.java b/src/jalview/ws/api/JalviewWebServiceI.java
new file mode 100644 (file)
index 0000000..ecc8bab
--- /dev/null
@@ -0,0 +1,19 @@
+package jalview.ws.api;
+
+import jalview.gui.WebserviceInfo;
+import jalview.ws.gui.WsJob;
+
+public interface JalviewWebServiceI
+{
+
+  void updateStatus(WsJob job);
+
+  boolean updateJobProgress(WsJob job) throws Exception;
+
+  boolean handleSubmitError(Throwable _lex, WsJob j, WebserviceInfo wsInfo)
+          throws Exception, Error;
+
+  boolean handleCollectionException(Exception e, WsJob msjob,
+          WebserviceInfo wsInfo);
+
+}
diff --git a/src/jalview/ws/api/JobId.java b/src/jalview/ws/api/JobId.java
new file mode 100644 (file)
index 0000000..2a092bd
--- /dev/null
@@ -0,0 +1,59 @@
+package jalview.ws.api;
+
+import java.time.Instant;
+import java.util.Date;
+
+public class JobId
+{
+  // TODO: JobId could include sequenceI anonymisation stuff
+  // TODO: getProgress() -> input stream to log file for job.
+  private String serviceType;
+
+  private String serviceImpl;
+
+  private String jobId;
+
+  private Instant creationTime;
+
+  public JobId(String serviceType, String serviceImpl, String id)
+  {
+    this.serviceType = serviceType;
+    this.serviceImpl = serviceImpl;
+    jobId = id;
+    creationTime = Instant.now();
+  }
+
+  @Override
+  public String toString()
+  {
+    return "" + serviceType + ":" + serviceImpl + ":" + jobId + "\nCreated "
+            + Date.from(creationTime);
+  }
+  /**
+   * a stringified version of the Job Id that can be saved in project.
+   */
+  public String getURI()
+  {
+    return jobId;
+  }
+
+  public String getServiceType()
+  {
+    return serviceType;
+  }
+
+  public String getServiceImpl()
+  {
+    return serviceImpl;
+  }
+
+  public String getJobId()
+  {
+    return jobId;
+  }
+
+  public Instant getCreationTime()
+  {
+    return creationTime;
+  }
+}
diff --git a/src/jalview/ws/api/MsaI.java b/src/jalview/ws/api/MsaI.java
new file mode 100644 (file)
index 0000000..3c426c0
--- /dev/null
@@ -0,0 +1,36 @@
+package jalview.ws.api;
+
+import jalview.datamodel.SequenceI;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.WsParamSetI;
+
+import java.util.List;
+
+/**
+ * MSA analysis interface
+ * 
+ * @author jprocter
+ * 
+ *         Generic job submission/management model: - A service instance
+ *         implements one or more analysis interfaces, a status interface, a
+ *         progress interface, and one or more results interface, plus any
+ *         informational/descriptional interfaces - analysis interfaces return
+ *         JobId or throw exceptions/errors.
+ * 
+ *
+ */
+public interface MsaI
+{
+  /**
+   * Given a set of sequences
+   * 
+   * @param toalign
+   * @param parameters
+   * @param list
+   * @return JobId or exceptions are thrown.
+   * @throws Throwable
+   */
+  public JobId align(List<SequenceI> toalign, WsParamSetI parameters,
+          List<ArgumentI> list)
+          throws Throwable;
+}
diff --git a/src/jalview/ws/api/MsaResultI.java b/src/jalview/ws/api/MsaResultI.java
new file mode 100644 (file)
index 0000000..38c0a0a
--- /dev/null
@@ -0,0 +1,13 @@
+package jalview.ws.api;
+
+import jalview.datamodel.AlignmentI;
+import jalview.ws.params.InvalidArgumentException;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+
+public interface MsaResultI
+{
+  public AlignmentI getAlignmentFor(JobId jobId)
+          throws InvalidArgumentException, ServerError, IOError;
+}
\ No newline at end of file
diff --git a/src/jalview/ws/api/MsaWithGuideTreeI.java b/src/jalview/ws/api/MsaWithGuideTreeI.java
new file mode 100644 (file)
index 0000000..6c2ff53
--- /dev/null
@@ -0,0 +1,24 @@
+package jalview.ws.api;
+
+import jalview.analysis.NJTree;
+import jalview.datamodel.SequenceI;
+import jalview.ws.params.InvalidArgumentException;
+import jalview.ws.params.WsParamSetI;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+import java.util.List;
+
+public interface MsaWithGuideTreeI
+{
+  /**
+   * Given a set of sequences
+   * 
+   * @param toalign
+   * @param parameters
+   * @return JobId or exceptions are thrown.
+   */
+  public JobId align(List<SequenceI> toalign, NJTree guideTree,
+          WsParamSetI parameters)
+          throws InvalidArgumentException, ServerError, IOError;
+}
\ No newline at end of file
diff --git a/src/jalview/ws/api/MultipleSequenceAlignmentI.java b/src/jalview/ws/api/MultipleSequenceAlignmentI.java
new file mode 100644 (file)
index 0000000..10b8383
--- /dev/null
@@ -0,0 +1,13 @@
+package jalview.ws.api;
+
+/**
+ * A simple parameterisable multiple sequence alignment service
+ * 
+ * @author jprocter
+ *
+ */
+public interface MultipleSequenceAlignmentI
+        extends JalviewWebServiceI, MsaI, MsaResultI
+{
+
+}
diff --git a/src/jalview/ws/api/ServiceWithParameters.java b/src/jalview/ws/api/ServiceWithParameters.java
new file mode 100644 (file)
index 0000000..cf82708
--- /dev/null
@@ -0,0 +1,16 @@
+package jalview.ws.api;
+
+import jalview.ws.params.ParamManager;
+
+public abstract class ServiceWithParameters extends UIinfo
+{
+
+  public ServiceWithParameters(String serviceType, String action,
+          String name, String description, String hosturl)
+  {
+    super(serviceType, action, name, description, hosturl);
+  }
+
+  public abstract void initParamStore(ParamManager userParameterStore);
+
+}
diff --git a/src/jalview/ws/api/TreeResultI.java b/src/jalview/ws/api/TreeResultI.java
new file mode 100644 (file)
index 0000000..1a0c3bd
--- /dev/null
@@ -0,0 +1,14 @@
+package jalview.ws.api;
+
+import jalview.analysis.NJTree;
+import jalview.ws.params.InvalidArgumentException;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+
+public interface TreeResultI
+{
+
+  public NJTree getTreeFor(JobId jobId)
+          throws InvalidArgumentException, ServerError, IOError;
+}
\ No newline at end of file
diff --git a/src/jalview/ws/api/UIinfo.java b/src/jalview/ws/api/UIinfo.java
new file mode 100644 (file)
index 0000000..8ef4d5b
--- /dev/null
@@ -0,0 +1,164 @@
+package jalview.ws.api;
+
+import jalview.ws.params.ParamDatastoreI;
+
+/**
+ * Service UI Info { Action, Specific Name of Service, Brief Description }
+ */
+
+public class UIinfo
+{
+  private String ServiceType;
+
+  public UIinfo(String serviceType, String action, String name,
+          String description, String hosturl)
+  {
+    this.setServiceType(serviceType == null ? "" : serviceType);
+    this.Action = action == null ? "" : action;
+    this.description = description == null ? "" : description;
+    this.Name = name == null ? "" : name;
+    this.hostURL = hosturl;
+  }
+
+  /**
+   * The type of analysis the service performs
+   */
+  public String getServiceType()
+  {
+    return ServiceType;
+  }
+
+  public void setServiceType(String serviceType)
+  {
+    ServiceType = serviceType;
+  }
+
+  /**
+   * The action when the service performs the analysis
+   */
+  public String getAction()
+  {
+    return Action;
+  }
+
+  public void setAction(String action)
+  {
+    Action = action;
+  }
+
+  /**
+   * name shown to user
+   * 
+   * @return
+   */
+  public String getName()
+  {
+    return Name;
+  }
+
+  public void setName(String name)
+  {
+    Name = name;
+  }
+
+  /**
+   * Detailed description (may include references, URLs, html,etc)
+   * 
+   * @return
+   */
+  public String getDescription()
+  {
+    return description;
+  }
+
+  public void setDescription(String description)
+  {
+    this.description = description;
+  }
+
+  @Override
+  public boolean equals(Object object)
+  {
+    if (object == null || !(object instanceof UIinfo))
+    {
+      return false;
+    }
+    UIinfo other = (UIinfo) object;
+
+    return (ServiceType == null && other.getServiceType() == null
+            || ServiceType != null && other.getServiceType() != null
+                    && ServiceType.equals(other.getServiceType()))
+            && (hostURL == null && other.getHostURL() == null
+                    || hostURL != null && other.getHostURL() != null
+                            && hostURL.equals(other.getHostURL()))
+            && (Name == null && other.getName() == null
+                    || Name != null && other.getName() != null
+                            && Name.equals(other.getName()))
+            && (Action == null && other.getAction() == null
+                    || Action != null && other.getAction() != null
+                            && Action.equals(other.getAction()))
+            && (description == null && other.getDescription() == null
+                    || description != null && other.getDescription() != null
+                            && description.equals(other.getDescription()));
+  }
+
+  /**
+   * @return short description of what the service will do
+   */
+  public String getActionText()
+  {
+    return getAction() + " with " + getName();
+  }
+
+  String Action;
+
+  String Name;
+
+  String description;
+
+  String hostURL;
+
+  public String getHostURL()
+  {
+    return hostURL;
+  }
+
+  public ParamDatastoreI getParamStore()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  /**
+   * 
+   * @return true if the service has parameters (ie is instance of
+   *         jalview.ws.api.ServiceWithParameters)
+   */
+  public boolean hasParameters()
+  {
+    // TODO Auto-generated method stub
+    return false;
+  }
+
+  private String docUrl = null;
+
+  /**
+   * set the URL that will be offered to show documentation for the service
+   * 
+   * @param url
+   */
+  public void setDocumentationUrl(String url)
+  {
+    docUrl = url;
+  }
+
+  public boolean hasDocumentationUrl()
+  {
+    return docUrl != null && docUrl.length() > 7;
+  }
+
+  public String getDocumentationUrl()
+  {
+    return docUrl;
+  }
+}
\ No newline at end of file
diff --git a/src/jalview/ws/ebi/HmmerJSONProcessor.java b/src/jalview/ws/ebi/HmmerJSONProcessor.java
new file mode 100644 (file)
index 0000000..428c498
--- /dev/null
@@ -0,0 +1,331 @@
+package jalview.ws.ebi;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+import jalview.io.FileParse;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+
+public class HmmerJSONProcessor
+{
+  /**
+   * result to be annotated. may not be null
+   */
+  AlignmentI resultAl;
+
+  /**
+   * viewport on the alignment. may be null at construction time
+   */
+  AlignmentViewport viewAl = null;
+
+  public HmmerJSONProcessor(AlignmentI searchResult)
+  {
+    resultAl = searchResult;
+  }
+
+  public void parseFrom(FileParse jsonsource) throws IOException,
+          OutOfMemoryError
+  {
+    JSONParser hmmerResultParser = new JSONParser();
+    Object jsonResults = null;
+    try
+    {
+      jsonResults = hmmerResultParser.parse(jsonsource.getReader());
+    } catch (Exception p)
+    {
+      throw new IOException("While parsing from " + jsonsource.getInFile(),
+              p);
+    }
+    if (jsonResults == null)
+    {
+      throw new IOException("No data at" + jsonsource.getInFile());
+    }
+    if (!(jsonResults instanceof JSONObject))
+    {
+      throw new IOException("Unexpected JSON model at "
+              + jsonsource.getInFile());
+    }
+    try
+    {
+      JSONObject hmmsearchr = (JSONObject) ((JSONObject) jsonResults)
+              .get("results");
+      // now process the hits
+      addStatistics((JSONObject) hmmsearchr.get("stats"));
+      JSONArray jsonArray = (JSONArray) hmmsearchr.get("hits");
+      long p = 1;
+      for (Object hit : jsonArray)
+      {
+        JSONObject hmmhit = (JSONObject) hit;
+        addHit(hmmhit, p++);
+      }
+    } catch (ClassCastException q)
+    {
+      throw new IOException("Unexpected JSON model content at "
+              + jsonsource.getInFile(), q);
+    }
+  }
+
+  /**
+   * 
+   * @param object
+   *          - actually a JSONObject key value set of search statistics.
+   */
+  public void addStatistics(JSONObject stats)
+  {
+    for (Object stat : stats.keySet())
+    {
+      String key = (String) stat;
+      Object val = stats.get(key);
+      resultAl.setProperty(key, "" + val);
+    }
+  }
+
+  // encodings for JSON keys
+  /**
+   * score becomes sequence associated AlignmentAnnotation
+   */
+  private String[] score = { "aliId", "ali_IdCount", "bitscore", "ievalue",
+      "aliSim", "aliSimCount", "aliL", "aliSim", "ievalue", "cevalue" };
+
+  /**
+   * attrib becomes numeric or binary attribute for sequence with respect to
+   * this hmmsearch run
+   */
+  private String[] attrib = { "bias", "oasc", "is_included", "is_reported" };
+
+  /**
+   * name of the hmmsearch query
+   */
+  private String[] label = { "alihmmname" // (query label?)},
+  };
+
+  /**
+   * integer attributes for each
+   */
+  private String[] ipos = { "alihmmfrom", "alihmmto" }, pos_l = {
+      "alimline", "alimodel", "alirfline" };
+
+  /**
+   * positional quantitative annotation encoded as strings.
+   */
+  private String[] pos_nscore = { "alippline" };
+
+  //
+  // mapping of keys to types of property on sequence
+  //
+  public void addHit(JSONObject hmmrhit, long p)
+  {
+    String sname = (String) hmmrhit.get("name");
+    SequenceI[] hits = resultAl.findSequenceMatch(sname);
+    if (hits == null)
+    {
+      System.err.println("No seq for " + sname);
+    }
+    double pvalue = (Double) hmmrhit.get("pvalue");
+
+    double evalue = Double.valueOf("" + hmmrhit.get("evalue"));
+    for (Object domainhit : ((JSONArray) hmmrhit.get("domains")))
+    {
+      JSONObject dhit = (JSONObject) domainhit;
+      // dhit.get(key)
+
+      // alihmmfrom,alihmmto alimodel
+      long alihmmfrom = (long) dhit.get("alihmmfrom"), alihmmto = (long) dhit
+              .get("alihmmto"), alisqfrom = (long) dhit.get("alisqfrom"), alisqto = (long) dhit
+              .get("alisqto");
+
+      // alisqfrom,alisqto,aliaseq
+
+      // alippline
+      String aliaseq = (String) dhit.get("aliaseq"), alimodel = (String) dhit
+              .get("alimodel"), ppline = (String) dhit.get("alippline");
+      //
+      int found = 0;
+      SequenceI firsthit = null;
+      for (SequenceI hitseq : hits)
+      {
+        // match alisqfrom,alisqto,seq
+        if (hitseq.getStart() == alisqfrom && hitseq.getEnd() == alisqto)
+        {
+          if (found == 0)
+          {
+            firsthit = hitseq;
+          }
+          found++; // annotated a sequence
+          AlignmentAnnotation alipp = parsePosteriorProb(ppline);
+          AlignmentAnnotation pval = new AlignmentAnnotation("p-value",
+                  "hmmer3 pvalue", pvalue);
+          AlignmentAnnotation eval = new AlignmentAnnotation("e-value",
+                  "hmmer3 evalue", evalue);
+          pval.setCalcId("HMMER3");
+          eval.setCalcId("HMMER3");
+          alipp.setCalcId("HMMER3");
+          hitseq.addAlignmentAnnotation(pval);
+          hitseq.addAlignmentAnnotation(eval);
+          alipp.createSequenceMapping(hitseq, hitseq.getStart(), false);
+          hitseq.addAlignmentAnnotation(alipp);
+          String arch;
+          hitseq.addSequenceFeature(new SequenceFeature(
+                  "Pfam Domain Architecture", (hmmrhit.get("archindex"))
+                          + " " + (arch = (String) hmmrhit.get("arch")), 0,
+                  0,
+                  (hmmrhit.get("archScore") != null ? Integer
+                          .valueOf((String) hmmrhit.get("archScore")) : 0f),
+                  "HMMER3"));
+          addArchGroup(hitseq, arch);
+          alipp.setScore(Double.valueOf("" + dhit.get("bitscore")));
+          alipp.adjustForAlignment();
+          resultAl.addAnnotation(pval);
+          resultAl.addAnnotation(eval);
+          resultAl.addAnnotation(alipp);
+          alipp.validateRangeAndDisplay();
+        }
+      }
+      // look for other sequences represented by this hit and create rep groups
+      // could be in "pdbs", or ..
+      addRedundantSeqGroup(firsthit, alisqfrom, alisqto,
+              (JSONArray) hmmrhit.get("seqs"), true);
+    }
+  }
+
+  /**
+   * series of operations to perform for the viewpanel associated with the
+   * alignment
+   */
+  private List<Runnable> viewOps = new ArrayList<Runnable>();
+
+  public void updateView(AlignmentViewport view)
+  {
+    viewAl = view;
+    for (Runnable op : viewOps)
+    {
+      op.run();
+    }
+  }
+
+  private void addRedundantSeqGroup(final SequenceI firsthit,
+          long alisqfrom, long alisqto, JSONArray others, boolean justDelete)
+  {
+    if (others != null)
+    {
+      final SequenceGroup repgroup = new SequenceGroup();
+      repgroup.setSeqrep(firsthit);
+      repgroup.addOrRemove(firsthit, false);
+      repgroup.setStartRes(0);
+      repgroup.setEndRes(resultAl.getWidth() - 1);
+      for (Object otherseq : others.toArray(new JSONObject[0]))
+      {
+        String repseq = (String) ((JSONObject) otherseq).get("dn");
+        SequenceI[] other = resultAl.findSequenceMatch(repseq);
+        if (other != null && other.length > 0)
+        {
+          if (justDelete)
+          {
+            for (SequenceI oth : other)
+            {
+              resultAl.deleteSequence(oth);
+            }
+            ;
+          }
+          else
+          {
+            int ofound = 0;
+            for (SequenceI oth : other)
+            {
+              if (oth.getStart() == alisqfrom && oth.getEnd() == alisqto)
+              {
+                ofound++;
+                repgroup.addSequence(oth, false);
+              }
+            }
+            if (ofound == 0)
+            {
+              System.err.println("Warn - no match for redundant hit "
+                      + repseq + "/" + alisqfrom + "-" + alisqto);
+            }
+            if (ofound > 1)
+            {
+              System.err
+                      .println("Warn - multiple matches for redundant hit "
+                              + repseq + "/" + alisqfrom + "-" + alisqto);
+            }
+          }
+        }
+      }
+      if (repgroup.getSequences().size() > 1)
+      {
+        // queue a hide operation
+        final HmmerJSONProcessor me = this;
+        viewOps.add(new Runnable()
+        {
+          @Override
+          public void run()
+          {
+            me.viewAl.hideRepSequences(firsthit, repgroup);
+          }
+        });
+      }
+    }
+  }
+
+  Map<String, SequenceGroup> groups = new HashMap<String, SequenceGroup>();
+
+  private void addArchGroup(SequenceI seqToAdd, String groupNam)
+  {
+    SequenceGroup sg = groups.get(groupNam);
+    if (sg == null)
+    {
+      sg = new SequenceGroup();
+      sg.setName(groupNam);
+      sg.addSequence(seqToAdd, false);
+      sg.setStartRes(0);
+      sg.setEndRes(resultAl.getWidth() - 1);
+      groups.put(groupNam, sg);
+      resultAl.addGroup(sg);
+    }
+    else
+    {
+      sg.addSequence(seqToAdd, false);
+    }
+  }
+
+  private AlignmentAnnotation parsePosteriorProb(String ppline)
+  {
+    Annotation[] ae = new Annotation[ppline.length()];
+    int spos = 0;
+    for (int i = 0, iSize = ppline.length(); i < iSize; i++)
+    {
+      char pp = ppline.charAt(i);
+      if (pp == '*')
+      {
+        ae[spos++] = new Annotation(10f);
+      }
+      else
+      {
+        if (pp >= '0' && pp <= '9')
+        {
+          ae[spos++] = new Annotation(Integer.valueOf("" + pp));
+        }
+      }
+    }
+    AlignmentAnnotation pprob = new AlignmentAnnotation(
+            "Posterior Probability",
+            "Likelihood of HMM fit at each hit position.", ae);
+    pprob.graph = AlignmentAnnotation.BAR_GRAPH;
+    pprob.visible = false;
+    return pprob;
+  }
+}
diff --git a/src/jalview/ws/ebi/hmmerClient.java b/src/jalview/ws/ebi/hmmerClient.java
new file mode 100644 (file)
index 0000000..41cd0d8
--- /dev/null
@@ -0,0 +1,319 @@
+package jalview.ws.ebi;
+
+import jalview.datamodel.AlignmentI;
+import jalview.io.AppletFormatAdapter;
+import jalview.io.DataSourceType;
+import jalview.io.FileFormat;
+import jalview.io.FileParse;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.regex.Matcher;
+
+import org.apache.axis.transport.http.HTTPConstants;
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import compbio.util.FileUtil;
+
+public class hmmerClient
+{
+  /**
+   * URLs for ebi api
+   */
+  static String baseUrl = "http://www.ebi.ac.uk/Tools/hmmer",
+          jackH = "/search/jackhmmer", phmmer = "/search/phmmer",
+          hmmscan = "/search/hmmscan", hmmsearch = "/search/hmmsearch";
+
+  static String edseq = ">2abl_A mol:protein length:163  ABL TYROSINE KINASE\nMGPSENDPNLFVALYDFVASGDNTLSITKGEKLRVLGYNHNGEWCEAQTKNGQGWVPSNYITPVNSLEKHS\nWYHGPVSRNAAEYLLSSGINGSFLVRESESSPGQRSISLRYEGRVYHYRINTASDGKLYVSSESRFNTLAE\nLVHHHSTVADGLITTLHYPAP";
+
+  public static void main(String[] args)
+  {
+    String instr = edseq;
+    if (args.length > 0)
+    {
+      try
+      {
+        instr = FileUtil.readFileToString(new File(args[0]));
+      } catch (Exception f)
+      {
+        f.printStackTrace();
+        return;
+      }
+    }
+    String res = new hmmerClient().submitJackhmmerSearch(instr,
+            "jackhmmer", "pdb", 5);
+    if (res == null)
+    {
+      throw new Error("Failed.");
+    }
+    System.out.println("Result\n" + res);
+    return;
+  }
+
+  /**
+   * 
+   * @param input
+   *          - fasta or other formatted sequence or alignment
+   * @param algo
+   *          - jackhmmer
+   * @param db
+   *          - pdb, uniprot, etc.
+   * @param niter
+   *          number of iterations
+   * @return job id
+   */
+  String submitJackhmmerSearch(String input, String algo, String db,
+          int niter)
+  {
+    JSONObject inparam = new JSONObject();
+    HttpPost jackhp = new HttpPost(baseUrl + jackH);
+    String lastiter = null;
+    try
+    {
+      inparam.put("algo", algo);
+      inparam.put("seq", input);
+      inparam.put("seqdb", db);
+      inparam.put("iterations", niter);
+      // #Now POST the request and generate the search job.
+      // dumb json post service
+      jackhp.setHeader("content-type", "application/json");
+      jackhp.setEntity(new StringEntity(inparam.toString()));
+    } catch (Exception f)
+    {
+      f.printStackTrace();
+      return null;
+    }
+    HttpResponse r = null;
+    try
+    {
+      DefaultHttpClient httpCl = new DefaultHttpClient();
+
+      r = httpCl.execute(jackhp);
+
+    } catch (Exception x)
+    {
+      System.err.println("Submit failed.");
+      x.printStackTrace();
+    }
+    if (r.getStatusLine().getStatusCode() != 201)
+    {
+      throw new Error(r.toString());
+    }
+    // get uid for job
+    String jobid = null, redir = null;
+    try
+    {
+      JSONObject res = new JSONObject(EntityUtils.toString(r.getEntity()));
+      jobid = res.getString("job_id");
+
+      Header[] loc;
+      if ((loc = r.getHeaders(HTTPConstants.HEADER_LOCATION)) != null
+              && loc.length > 0)
+      {
+        if (loc.length > 1)
+        {
+          System.err
+                  .println("Ignoring additional "
+                          + (loc.length - 1)
+                          + " location(s) provided in response header ( next one is '"
+                          + loc[1].getValue() + "' )");
+        }
+        redir = loc[0].getValue();
+      }
+    } catch (Exception x)
+    {
+      System.err.println("job id extraction failed.");
+      x.printStackTrace();
+    }
+    int tries = 0;
+    boolean finished = false;
+    JSONObject jobstate = null;
+    do
+    {
+      try
+      {
+        DefaultHttpClient httpCl = new DefaultHttpClient();
+
+        HttpGet jackcheck = new HttpGet(redir);
+        jackcheck.setHeader("content-type", "application/json");
+        r = httpCl.execute(jackcheck);
+        switch (r.getStatusLine().getStatusCode())
+        {
+        case 200:
+          jobstate = new JSONObject(EntityUtils.toString(r.getEntity()));
+          String st = jobstate.getString("status");
+          if ("DONE".equals(st))
+          {
+            finished = true;
+          }
+          if ("ERROR".equals(st))
+          {
+            System.err.println("Error");
+            finished = true;
+          }
+          if ("PEND".equals(st) || "RUN".equals("st"))
+          {
+            JSONArray iters = jobstate.getJSONArray("result");
+            lastiter = iters.getJSONObject(iters.length() - 1).getString(
+                    "uuid");
+            if (lastiter.length() > 0)
+            {
+              java.util.regex.Pattern p = java.util.regex.Pattern
+                      .compile(".+(\\d+)");
+              Matcher m = p.matcher(lastiter);
+              if (m.matches())
+              {
+                System.out.println("On iteration " + m.group(1));
+              }
+            }
+          }
+          break;
+
+        default:
+          tries++;
+          Thread.sleep(2000);
+        }
+      } catch (Exception q)
+      {
+        q.printStackTrace();
+        return null;
+      }
+    } while (!finished && tries < 50);
+
+    if (!finished)
+    {
+      System.err.println("Giving up with job " + jobid + " at " + redir);
+      return null;
+    }
+    // get results
+    // http://www.ebi.ac.uk/Tools/hmmer/download/60048B38-7CEC-11E5-A230-CED6D26C98AD.5/score?format=csv
+    // 1gri_A 1gri_A 217 jackhmmer - 163 4.7e-62 212.4 0.1 1 2 4.4e-46 2.1e-43
+    // 151.758316040039 0.04 11 151 3 139 1 150 0.94 GROWTH FACTOR BOUND PROTEIN
+    // 2 1cj1_J 1gri_B
+    // 1gri_A 1gri_A 217 jackhmmer - 163 4.7e-62 212.4 0.1 2 2 1.6e-17 7.9e-15
+    // 58.8796501159668 0.01 7 66 157 215 153 216 0.95 GROWTH FACTOR BOUND
+    // PROTEIN 2 1cj1_J 1gri_B
+    // 4h1o_A 4h1o_A 560 jackhmmer - 163 2.1e-57 197.3 0.0 1 2 7.5e-28 3.6e-25
+    // 92.4921493530273 0.00 65 161 20 122 17 124 0.95 Tyrosine-protein
+    // phosphatase non-receptor typ 4h1o_A
+    //
+    // 4h1o_A 4h1o_A 560 jackhmmer - 163 2.1e-57 197.3 0.0 2 2 7.6e-31 3.7e-28
+    // 102.219146728516 0.03 66 161 127 236 124 238 0.94 Tyrosine-protein
+    // phosphatase non-receptor typ 4h1o_A
+    //
+    // $ua->get( $rootUrl."/results/".$lastIteration->{uuid} . "/score"
+    return lastiter;
+    /*
+     * * #Job should have finished, but we may have converged, so get the last
+     * job. my $results = $json->decode( $response->content ); my $lastIteration
+     * = pop( @{ $results->{result} } ); #Now fetch the results of the last
+     * iteration my $searchResult = $ua->get( $rootUrl."/results/" .
+     * $lastIteration->{uuid} . "/score", 'Accept' => 'application/json' );
+     * unless( $searchResult->status_line eq "200 OK"){ die
+     * "Failed to get search results\n"; }
+     * 
+     * #Decode the content of the full set of results $results = $json->decode(
+     * $searchResult->content ); print
+     * "Matched ".$results->{'results'}->{'stats'}->{'nincluded'}." sequences
+     * ($lastIteration->{uuid})!\n"; #Now do something more interesting with the
+     * results......
+     */
+  }
+
+  /**
+   * retrieve an alignment annotated with scores from JackHmmer
+   * 
+   * @param jobid
+   * @param dataset
+   * @return
+   */
+  AlignmentI retrieveJackhmmerResult(String jobid, AlignmentI dataset)
+          throws OutOfMemoryError, IOException
+  {
+    AlignmentI searchResult = null;
+
+    // get results
+
+    searchResult = new AppletFormatAdapter().readFile(baseUrl
+            + "/download/" + jobid + "/score?format=afa&t=.gz",
+            DataSourceType.URL, FileFormat.Fasta);
+
+    // TODO extract gapped columns as '.' - inserts to query profile
+
+    // TODO match up jackhammer results to dataset.
+
+    // do scores
+    FileParse jsonsource = new FileParse(baseUrl + "/download/" + jobid
+            + "/score?format=json", DataSourceType.URL);
+    if (!jsonsource.isValid())
+    {
+      throw new IOException("Couldn't access scores for Jackhammer results");
+    }
+    readJackhmmerScores(searchResult, jsonsource);
+    return searchResult;
+  }
+
+  /**
+   * // 1gri_A 1gri_A 217 jackhmmer - 163 4.7e-62 212.4 0.1 1 2 4.4e-46 2.1e-43
+   * 
+   * // 151.758316040039 0.04 11 151 3 139 1 150 0.94 GROWTH FACTOR BOUND
+   * PROTEIN // 2 1cj1_J 1gri_B // 1gri_A 1gri_A 217 jackhmmer - 163 4.7e-62
+   * 212.4 0.1 2 2 1.6e-17 7.9e-15 // 58.8796501159668 0.01 7 66 157 215 153 216
+   * 0.95 GROWTH FACTOR BOUND // PROTEIN 2 1cj1_J 1gri_B // 4h1o_A 4h1o_A 560
+   * jackhmmer - 163 2.1e-57 197.3 0.0 1 2 7.5e-28 3.6e-25 // 92.4921493530273
+   * 0.00 65 161 20 122 17 124 0.95 Tyrosine-protein // phosphatase non-receptor
+   * typ 4h1o_A
+   */
+  private static String[] _hmmsearchcols = new String[] { "acc", "name", "" };
+
+  private void readJackhmmerScores(AlignmentI searchResult,
+          FileParse jsonsource) throws IOException, OutOfMemoryError
+  {
+    HmmerJSONProcessor hjp = new HmmerJSONProcessor(searchResult);
+    hjp.parseFrom(jsonsource);
+
+    // http://www.ebi.ac.uk/Tools/hmmer/download/60048B38-7CEC-11E5-A230-CED6D26C98AD.5/score?format=csv
+    // 1gri_A 1gri_A 217 jackhmmer - 163 4.7e-62 212.4 0.1 1 2 4.4e-46 2.1e-43
+    // 151.758316040039 0.04 11 151 3 139 1 150 0.94 GROWTH FACTOR BOUND PROTEIN
+    // 2 1cj1_J 1gri_B
+    // 1gri_A 1gri_A 217 jackhmmer - 163 4.7e-62 212.4 0.1 2 2 1.6e-17 7.9e-15
+    // 58.8796501159668 0.01 7 66 157 215 153 216 0.95 GROWTH FACTOR BOUND
+    // PROTEIN 2 1cj1_J 1gri_B
+    // 4h1o_A 4h1o_A 560 jackhmmer - 163 2.1e-57 197.3 0.0 1 2 7.5e-28 3.6e-25
+    // 92.4921493530273 0.00 65 161 20 122 17 124 0.95 Tyrosine-protein
+    // phosphatase non-receptor typ 4h1o_A
+    // each line scores a fragment
+    // so for a combined score ?
+
+    /**
+     * for a sequence q sort any t against q according to overallScore(q,t)
+     * maxFragment(q,t) in sequence features parlance: for alignment
+     * s.getFeature("overallScore",q) -> range on q and range on s
+     * 
+     * 
+     */
+
+    // 151.758316040039 0.04 11 151 3 139 1 150 0.94 GROWTH FACTOR BOUND PROTEIN
+    // 2 1cj1_J 1gri_B
+    // 1gri_A 1gri_A 217 jackhmmer - 163 4.7e-62 212.4 0.1 2 2 1.6e-17 7.9e-15
+    // 58.8796501159668 0.01 7 66 157 215 153 216 0.95 GROWTH FACTOR BOUND
+    // PROTEIN 2 1cj1_J 1gri_B
+    // 4h1o_A 4h1o_A 560 jackhmmer - 163 2.1e-57 197.3 0.0 1 2 7.5e-28 3.6e-25
+    // 92.4921493530273 0.00 65 161 20 122 17 124 0.95 Tyrosine-protein
+    // phosphatase non-receptor typ 4h1o_A
+    //
+    // 4h1o_A 4h1o_A 560 jackhmmer - 163 2.1e-57 197.3 0.0 2 2 7.6e-31 3.7e-28
+    // 102.219146728516 0.03 66 161 127 236 124 238 0.94 Tyrosine-protein
+    // phosphatase non-receptor typ 4h1o_A
+
+  }
+
+}
diff --git a/src/jalview/ws/gui/MsaWSJob.java b/src/jalview/ws/gui/MsaWSJob.java
new file mode 100644 (file)
index 0000000..86d299a
--- /dev/null
@@ -0,0 +1,381 @@
+package jalview.ws.gui;
+
+import jalview.analysis.AlignSeq;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentOrder;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.util.MessageManager;
+import jalview.ws.api.JobId;
+import jalview.ws.jws2.dm.JabaWsParamSet;
+import jalview.ws.params.ArgumentI;
+
+import java.util.ArrayList;
+import java.util.Vector;
+
+class MsaWSJob extends WsJob
+{
+  /**
+   * holds basic MSA analysis configuration - todo - encapsulate
+   */
+  private final MsaWSThread msaWSThread;
+
+  long lastChunk = 0;
+
+  /**
+   * input
+   */
+  ArrayList<SequenceI> seqs = new ArrayList<>();
+
+  /**
+   * output
+   */
+  AlignmentI alignment;
+
+  // set if the job didn't get run - then the input is simply returned to the
+  // user
+  private boolean returnInput = false;
+
+  /**
+   * MsaWSJob
+   * 
+   * @param jobNum
+   *          int
+   * @param msaWSThread
+   *          TODO - abstract the properties provided by the thread
+   * @param jobId
+   *          String
+   */
+  public MsaWSJob(MsaWSThread msaWSThread, int jobNum, SequenceI[] inSeqs)
+  {
+    this.msaWSThread = msaWSThread;
+    this.jobnum = jobNum;
+    if (!prepareInput(inSeqs, 2))
+    {
+      submitted = true;
+      subjobComplete = true;
+      returnInput = true;
+    }
+
+  }
+
+  Vector<String[]> emptySeqs = new Vector();
+
+  /**
+   * prepare input sequences for MsaWS service
+   * 
+   * @param seqs
+   *          jalview sequences to be prepared
+   * @param minlen
+   *          minimum number of residues required for this MsaWS service
+   * @return true if seqs contains sequences to be submitted to service.
+   */
+  // TODO: return compbio.seqs list or nothing to indicate validity.
+  private boolean prepareInput(SequenceI[] seqs, int minlen)
+  {
+    // TODO: service specific input data is generated in this method - for
+    // JABAWS it is client-side
+    // prepared, but for Slivka it could be uploaded at this stage.
+
+    int nseqs = 0;
+    if (minlen < 0)
+    {
+      throw new Error(MessageManager.getString(
+              "error.implementation_error_minlen_must_be_greater_zero"));
+    }
+    for (int i = 0; i < seqs.length; i++)
+    {
+      if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
+      {
+        nseqs++;
+      }
+    }
+    boolean valid = nseqs > 1; // need at least two seqs
+    Sequence seq;
+    for (int i = 0, n = 0; i < seqs.length; i++)
+    {
+      String newname = jalview.analysis.SeqsetUtils.unique_name(i); // same
+      // for
+      // any
+      // subjob
+      SeqNames.put(newname,
+              jalview.analysis.SeqsetUtils.SeqCharacterHash(seqs[i]));
+      if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
+      {
+        // make new input sequence with or without gaps
+        seq = new Sequence(newname,
+                (this.msaWSThread.submitGaps) ? seqs[i].getSequenceAsString()
+                        : AlignSeq.extractGaps(
+                                jalview.util.Comparison.GapChars,
+                                seqs[i].getSequenceAsString()));
+        this.seqs.add(seq);
+      }
+      else
+      {
+        String empty = null;
+        if (seqs[i].getEnd() >= seqs[i].getStart())
+        {
+          empty = (this.msaWSThread.submitGaps) ? seqs[i].getSequenceAsString()
+                  : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
+                          seqs[i].getSequenceAsString());
+        }
+        emptySeqs.add(new String[] { newname, empty });
+      }
+    }
+    return valid;
+  }
+
+  /**
+   * 
+   * @return true if getAlignment will return a valid alignment result.
+   */
+  @Override
+  public boolean hasResults()
+  {
+    if (subjobComplete && isFinished() && (alignment != null
+            || (emptySeqs != null && emptySeqs.size() > 0)))
+    {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * 
+   * get the alignment including any empty sequences in the original order
+   * with original ids. Caller must access the alignment.getMetadata() object
+   * to annotate the final result passsed to the user.
+   * 
+   * @return { SequenceI[], AlignmentOrder }
+   */
+  public Object[] getAlignment()
+  {
+    // TODO: make this generic based on MsaResultI
+    // TODO: decide if the data loss for this return signature is avoidable
+    // (ie should we just return AlignmentI instead ?)
+    if (hasResults())
+    {
+      SequenceI[] alseqs = null;
+      char alseq_gapchar = '-';
+      int alseq_l = 0;
+      alseqs = new SequenceI[alignment.getSequences().size()];
+      if (alignment.getSequences().size() > 0)
+      {
+        for (SequenceI seq : alignment
+                .getSequences())
+        {
+          alseqs[alseq_l++] = new Sequence(seq);
+        }
+        alseq_gapchar = alignment.getGapCharacter();
+
+      }
+      // add in the empty seqs.
+      if (emptySeqs.size() > 0)
+      {
+        SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
+        // get width
+        int i, w = 0;
+        if (alseq_l > 0)
+        {
+          for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
+          {
+            if (w < alseqs[i].getLength())
+            {
+              w = alseqs[i].getLength();
+            }
+            t_alseqs[i] = alseqs[i];
+            alseqs[i] = null;
+          }
+        }
+        // check that aligned width is at least as wide as emptySeqs width.
+        int ow = w, nw = w;
+        for (i = 0, w = emptySeqs.size(); i < w; i++)
+        {
+          String[] es = emptySeqs.get(i);
+          if (es != null && es[1] != null)
+          {
+            int sw = es[1].length();
+            if (nw < sw)
+            {
+              nw = sw;
+            }
+          }
+        }
+        // make a gapped string.
+        StringBuffer insbuff = new StringBuffer(w);
+        for (i = 0; i < nw; i++)
+        {
+          insbuff.append(alseq_gapchar);
+        }
+        if (ow < nw)
+        {
+          for (i = 0; i < alseq_l; i++)
+          {
+            int sw = t_alseqs[i].getLength();
+            if (nw > sw)
+            {
+              // pad at end
+              alseqs[i].setSequence(t_alseqs[i].getSequenceAsString()
+                      + insbuff.substring(0, sw - nw));
+            }
+          }
+        }
+        for (i = 0, w = emptySeqs.size(); i < w; i++)
+        {
+          String[] es = emptySeqs.get(i);
+          if (es[1] == null)
+          {
+            t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0],
+                    insbuff.toString(), 1, 0);
+          }
+          else
+          {
+            if (es[1].length() < nw)
+            {
+              t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
+                      es[0],
+                      es[1] + insbuff.substring(0, nw - es[1].length()),
+                      1, 1 + es[1].length());
+            }
+            else
+            {
+              t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
+                      es[0], es[1]);
+            }
+          }
+        }
+        alseqs = t_alseqs;
+      }
+      AlignmentOrder msaorder = new AlignmentOrder(alseqs);
+      // always recover the order - makes parseResult()'s life easier.
+      jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
+      // account for any missing sequences
+      jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
+      return new Object[] { alseqs, msaorder };
+    }
+    return null;
+  }
+
+  /**
+   * mark subjob as cancelled and set result object appropriatly
+   */
+  void cancel()
+  {
+    cancelled = true;
+    subjobComplete = true;
+    alignment = null;
+  }
+
+  /**
+   * 
+   * @return boolean true if job can be submitted.
+   */
+  @Override
+  public boolean hasValidInput()
+  {
+    // TODO: get attributes for this MsaWS instance to check if it can do two
+    // sequence alignment.
+    if (seqs != null && seqs.size() >= 2) // two or more sequences is valid ?
+    {
+      return true;
+    }
+    return false;
+  }
+
+  StringBuffer jobProgress = new StringBuffer();
+
+  @Override
+  public void setStatus(String string)
+  {
+    jobProgress.setLength(0);
+    jobProgress.append(string);
+  }
+
+  @Override
+  public String getStatus()
+  {
+    return jobProgress.toString();
+  }
+
+  @Override
+  public boolean hasStatus()
+  {
+    return jobProgress != null;
+  }
+
+  /**
+   * @return the lastChunk
+   */
+  public long getLastChunk()
+  {
+    return lastChunk;
+  }
+
+  /**
+   * @param lastChunk
+   *          the lastChunk to set
+   */
+  public void setLastChunk(long lastChunk)
+  {
+    this.lastChunk = lastChunk;
+  }
+
+  String alignmentProgram = null;
+
+  public String getAlignmentProgram()
+  {
+    return alignmentProgram;
+  }
+
+  public boolean hasArguments()
+  {
+    return (arguments != null && arguments.size() > 0)
+            || (preset != null && preset instanceof JabaWsParamSet);
+  }
+
+  /**
+   * add a progess header to status string containing presets/args used
+   */
+  public void addInitialStatus()
+  {
+    // TODO: decide if it is useful to report 'JABAWS format' argument lists
+    // rather than generic Jalview service arguments
+    if (preset != null)
+    {
+      jobProgress.append(
+              "Using " + (preset.isModifiable() ? "Server" : "User")
+                      + "Preset: " + preset.getName());
+      for (ArgumentI opt : preset.getArguments())
+      {
+        jobProgress.append(opt.getName() + " " + opt.getValue() + "\n");
+      }
+    }
+    else
+    {
+      if (arguments != null && arguments.size() > 0)
+      {
+        jobProgress.append("With custom parameters : \n");
+        // merge arguments with preset's own arguments.
+        for (ArgumentI opt : arguments)
+        {
+          jobProgress.append(opt.getName() + " " + opt.getValue() + "\n");
+        }
+      }
+      jobProgress.append("\nJob Output:\n");
+    }
+  }
+
+  JobId jobHandle = null;
+  public void setJobHandle(JobId align)
+  {
+    jobHandle = align;
+    setJobId(jobHandle.getJobId());
+
+  }
+
+  public JobId getJobHandle()
+  {
+    return jobHandle;
+  }
+
+}
\ No newline at end of file
similarity index 52%
rename from src/jalview/ws/jws2/MsaWSThread.java
rename to src/jalview/ws/gui/MsaWSThread.java
index db6e03f..7141e73 100644 (file)
  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
  * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
-package jalview.ws.jws2;
+package jalview.ws.gui;
 
-import jalview.analysis.AlignSeq;
 import jalview.bin.Cache;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.AlignmentView;
 import jalview.datamodel.HiddenColumns;
-import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.gui.SplitFrame;
 import jalview.gui.WebserviceInfo;
 import jalview.util.MessageManager;
+import jalview.ws.AWSThread;
 import jalview.ws.AWsJob;
 import jalview.ws.JobStateSummary;
 import jalview.ws.WSClientI;
-import jalview.ws.jws2.dm.JabaWsParamSet;
+import jalview.ws.api.CancellableI;
+import jalview.ws.api.JobId;
+import jalview.ws.api.MultipleSequenceAlignmentI;
+import jalview.ws.gui.WsJob.JobState;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.util.ArrayList;
-import java.util.Hashtable;
 import java.util.List;
-import java.util.Map;
-import java.util.Vector;
 
 import javax.swing.JInternalFrame;
 
-import compbio.data.msa.MsaWS;
-import compbio.metadata.Argument;
-import compbio.metadata.ChunkHolder;
-import compbio.metadata.JobStatus;
-import compbio.metadata.Preset;
-
-class MsaWSThread extends AWS2Thread implements WSClientI
+public class MsaWSThread extends AWSThread implements WSClientI
 {
   boolean submitGaps = false; // pass sequences including gaps to alignment
 
@@ -64,384 +58,13 @@ class MsaWSThread extends AWS2Thread implements WSClientI
 
   // order
 
-  class MsaWSJob extends JWs2Job
-  {
-    long lastChunk = 0;
-
-    WsParamSetI preset = null;
-
-    List<Argument> arguments = null;
-
-    /**
-     * input
-     */
-    ArrayList<compbio.data.sequence.FastaSequence> seqs = new ArrayList<compbio.data.sequence.FastaSequence>();
-
-    /**
-     * output
-     */
-    compbio.data.sequence.Alignment alignment;
-
-    // set if the job didn't get run - then the input is simply returned to the
-    // user
-    private boolean returnInput = false;
-
-    /**
-     * MsaWSJob
-     * 
-     * @param jobNum
-     *          int
-     * @param jobId
-     *          String
-     */
-    public MsaWSJob(int jobNum, SequenceI[] inSeqs)
-    {
-      this.jobnum = jobNum;
-      if (!prepareInput(inSeqs, 2))
-      {
-        submitted = true;
-        subjobComplete = true;
-        returnInput = true;
-      }
-
-    }
-
-    Hashtable<String, Map> SeqNames = new Hashtable();
-
-    Vector<String[]> emptySeqs = new Vector();
-
-    /**
-     * prepare input sequences for MsaWS service
-     * 
-     * @param seqs
-     *          jalview sequences to be prepared
-     * @param minlen
-     *          minimum number of residues required for this MsaWS service
-     * @return true if seqs contains sequences to be submitted to service.
-     */
-    // TODO: return compbio.seqs list or nothing to indicate validity.
-    private boolean prepareInput(SequenceI[] seqs, int minlen)
-    {
-      int nseqs = 0;
-      if (minlen < 0)
-      {
-        throw new Error(MessageManager.getString(
-                "error.implementation_error_minlen_must_be_greater_zero"));
-      }
-      for (int i = 0; i < seqs.length; i++)
-      {
-        if (seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
-        {
-          nseqs++;
-        }
-      }
-      boolean valid = nseqs > 1; // need at least two seqs
-      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
-        // subjob
-        SeqNames.put(newname,
-                jalview.analysis.SeqsetUtils.SeqCharacterHash(seqs[i]));
-        if (valid && seqs[i].getEnd() - seqs[i].getStart() > minlen - 1)
-        {
-          // make new input sequence with or without gaps
-          seq = new compbio.data.sequence.FastaSequence(newname,
-                  (submitGaps) ? seqs[i].getSequenceAsString()
-                          : AlignSeq.extractGaps(
-                                  jalview.util.Comparison.GapChars,
-                                  seqs[i].getSequenceAsString()));
-          this.seqs.add(seq);
-        }
-        else
-        {
-          String empty = null;
-          if (seqs[i].getEnd() >= seqs[i].getStart())
-          {
-            empty = (submitGaps) ? seqs[i].getSequenceAsString()
-                    : AlignSeq.extractGaps(jalview.util.Comparison.GapChars,
-                            seqs[i].getSequenceAsString());
-          }
-          emptySeqs.add(new String[] { newname, empty });
-        }
-      }
-      return valid;
-    }
-
-    /**
-     * 
-     * @return true if getAlignment will return a valid alignment result.
-     */
-    @Override
-    public boolean hasResults()
-    {
-      if (subjobComplete && isFinished() && (alignment != null
-              || (emptySeqs != null && emptySeqs.size() > 0)))
-      {
-        return true;
-      }
-      return false;
-    }
-
-    /**
-     * 
-     * get the alignment including any empty sequences in the original order
-     * with original ids. Caller must access the alignment.getMetadata() object
-     * to annotate the final result passsed to the user.
-     * 
-     * @return { SequenceI[], AlignmentOrder }
-     */
-    public Object[] getAlignment()
-    {
-      // is this a generic subjob or a Jws2 specific Object[] return signature
-      if (hasResults())
-      {
-        SequenceI[] alseqs = null;
-        char alseq_gapchar = '-';
-        int alseq_l = 0;
-        if (alignment.getSequences().size() > 0)
-        {
-          alseqs = new SequenceI[alignment.getSequences().size()];
-          for (compbio.data.sequence.FastaSequence seq : alignment
-                  .getSequences())
-          {
-            alseqs[alseq_l++] = new Sequence(seq.getId(),
-                    seq.getSequence());
-          }
-          alseq_gapchar = alignment.getMetadata().getGapchar();
-
-        }
-        // add in the empty seqs.
-        if (emptySeqs.size() > 0)
-        {
-          SequenceI[] t_alseqs = new SequenceI[alseq_l + emptySeqs.size()];
-          // get width
-          int i, w = 0;
-          if (alseq_l > 0)
-          {
-            for (i = 0, w = alseqs[0].getLength(); i < alseq_l; i++)
-            {
-              if (w < alseqs[i].getLength())
-              {
-                w = alseqs[i].getLength();
-              }
-              t_alseqs[i] = alseqs[i];
-              alseqs[i] = null;
-            }
-          }
-          // check that aligned width is at least as wide as emptySeqs width.
-          int ow = w, nw = w;
-          for (i = 0, w = emptySeqs.size(); i < w; i++)
-          {
-            String[] es = emptySeqs.get(i);
-            if (es != null && es[1] != null)
-            {
-              int sw = es[1].length();
-              if (nw < sw)
-              {
-                nw = sw;
-              }
-            }
-          }
-          // make a gapped string.
-          StringBuffer insbuff = new StringBuffer(w);
-          for (i = 0; i < nw; i++)
-          {
-            insbuff.append(alseq_gapchar);
-          }
-          if (ow < nw)
-          {
-            for (i = 0; i < alseq_l; i++)
-            {
-              int sw = t_alseqs[i].getLength();
-              if (nw > sw)
-              {
-                // pad at end
-                alseqs[i].setSequence(t_alseqs[i].getSequenceAsString()
-                        + insbuff.substring(0, sw - nw));
-              }
-            }
-          }
-          for (i = 0, w = emptySeqs.size(); i < w; i++)
-          {
-            String[] es = emptySeqs.get(i);
-            if (es[1] == null)
-            {
-              t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0],
-                      insbuff.toString(), 1, 0);
-            }
-            else
-            {
-              if (es[1].length() < nw)
-              {
-                t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
-                        es[0],
-                        es[1] + insbuff.substring(0, nw - es[1].length()),
-                        1, 1 + es[1].length());
-              }
-              else
-              {
-                t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(
-                        es[0], es[1]);
-              }
-            }
-          }
-          alseqs = t_alseqs;
-        }
-        AlignmentOrder msaorder = new AlignmentOrder(alseqs);
-        // always recover the order - makes parseResult()'s life easier.
-        jalview.analysis.AlignmentSorter.recoverOrder(alseqs);
-        // account for any missing sequences
-        jalview.analysis.SeqsetUtils.deuniquify(SeqNames, alseqs);
-        return new Object[] { alseqs, msaorder };
-      }
-      return null;
-    }
-
-    /**
-     * mark subjob as cancelled and set result object appropriatly
-     */
-    void cancel()
-    {
-      cancelled = true;
-      subjobComplete = true;
-      alignment = null;
-    }
-
-    /**
-     * 
-     * @return boolean true if job can be submitted.
-     */
-    @Override
-    public boolean hasValidInput()
-    {
-      // TODO: get attributes for this MsaWS instance to check if it can do two
-      // sequence alignment.
-      if (seqs != null && seqs.size() >= 2) // two or more sequences is valid ?
-      {
-        return true;
-      }
-      return false;
-    }
-
-    StringBuffer jobProgress = new StringBuffer();
-
-    public void setStatus(String string)
-    {
-      jobProgress.setLength(0);
-      jobProgress.append(string);
-    }
-
-    @Override
-    public String getStatus()
-    {
-      return jobProgress.toString();
-    }
-
-    @Override
-    public boolean hasStatus()
-    {
-      return jobProgress != null;
-    }
-
-    /**
-     * @return the lastChunk
-     */
-    public long getLastChunk()
-    {
-      return lastChunk;
-    }
-
-    /**
-     * @param lastChunk
-     *          the lastChunk to set
-     */
-    public void setLastChunk(long lastChunk)
-    {
-      this.lastChunk = lastChunk;
-    }
-
-    String alignmentProgram = null;
-
-    public String getAlignmentProgram()
-    {
-      return alignmentProgram;
-    }
-
-    public boolean hasArguments()
-    {
-      return (arguments != null && arguments.size() > 0)
-              || (preset != null && preset instanceof JabaWsParamSet);
-    }
-
-    public List<Argument> getJabaArguments()
-    {
-      List<Argument> newargs = new ArrayList<Argument>();
-      if (preset != null && preset instanceof JabaWsParamSet)
-      {
-        newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
-      }
-      if (arguments != null && arguments.size() > 0)
-      {
-        newargs.addAll(arguments);
-      }
-      return newargs;
-    }
-
-    /**
-     * add a progess header to status string containing presets/args used
-     */
-    public void addInitialStatus()
-    {
-      if (preset != null)
-      {
-        jobProgress.append("Using "
-                + (preset instanceof JabaPreset ? "Server" : "User")
-                + "Preset: " + preset.getName());
-        if (preset instanceof JabaWsParamSet)
-        {
-          for (Argument opt : ((JabaWsParamSet) preset).getjabaArguments())
-          {
-            jobProgress.append(
-                    opt.getName() + " " + opt.getDefaultValue() + "\n");
-          }
-        }
-      }
-      if (arguments != null && arguments.size() > 0)
-      {
-        jobProgress.append("With custom parameters : \n");
-        // merge arguments with preset's own arguments.
-        for (Argument opt : arguments)
-        {
-          jobProgress.append(
-                  opt.getName() + " " + opt.getDefaultValue() + "\n");
-        }
-      }
-      jobProgress.append("\nJob Output:\n");
-    }
-
-    public boolean isPresetJob()
-    {
-      return preset != null && preset instanceof JabaPreset;
-    }
-
-    public Preset getServerPreset()
-    {
-      return (isPresetJob()) ? ((JabaPreset) preset).p : null;
-    }
-  }
-
   String alTitle; // name which will be used to form new alignment window.
 
   AlignmentI dataset; // dataset to which the new alignment will be
 
   // associated.
 
-  @SuppressWarnings("unchecked")
-  MsaWS server = null;
+  MultipleSequenceAlignmentI server = null;
 
   /**
    * set basic options for this (group) of Msa jobs
@@ -451,7 +74,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
    * @param presorder
    *          boolean
    */
-  private MsaWSThread(MsaWS server, String wsUrl, WebserviceInfo wsinfo,
+  private MsaWSThread(MultipleSequenceAlignmentI server, String wsUrl,
+          WebserviceInfo wsinfo,
           jalview.gui.AlignFrame alFrame, AlignmentView alview,
           String wsname, boolean subgaps, boolean presorder)
   {
@@ -462,7 +86,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI
   }
 
   /**
-   * create one or more Msa jobs to align visible seuqences in _msa
+   * create one or more Msa jobs to align visible sequences in _msa
    * 
    * @param title
    *          String
@@ -475,7 +99,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
    * @param seqset
    *          Alignment
    */
-  MsaWSThread(MsaWS server2, WsParamSetI preset, List<Argument> paramset,
+  public MsaWSThread(MultipleSequenceAlignmentI server2, WsParamSetI preset,
+          List<ArgumentI> paramset,
           String wsUrl, WebserviceInfo wsinfo,
           jalview.gui.AlignFrame alFrame, String wsname, String title,
           AlignmentView _msa, boolean subgaps, boolean presorder,
@@ -490,23 +115,23 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     if (conmsa != null)
     {
       int nvalid = 0, njobs = conmsa.length;
-      jobs = new MsaWSJob[njobs];
+      jobs = new AWsJob[njobs];
       for (int j = 0; j < njobs; j++)
       {
         if (j != 0)
         {
-          jobs[j] = new MsaWSJob(wsinfo.addJobPane(), conmsa[j]);
+          jobs[j] = new MsaWSJob(this, wsinfo.addJobPane(), conmsa[j]);
         }
         else
         {
-          jobs[j] = new MsaWSJob(0, conmsa[j]);
+          jobs[j] = new MsaWSJob(this, 0, conmsa[j]);
         }
-        if (((MsaWSJob) jobs[j]).hasValidInput())
+        if (jobs[j].hasValidInput())
         {
           nvalid++;
         }
-        ((MsaWSJob) jobs[j]).preset = preset;
-        ((MsaWSJob) jobs[j]).arguments = paramset;
+        jobs[j].setPreset(preset);
+        jobs[j].setArguments(paramset);
         ((MsaWSJob) jobs[j]).alignmentProgram = wsname;
         if (njobs > 0)
         {
@@ -533,12 +158,14 @@ class MsaWSThread extends AWS2Thread implements WSClientI
   @Override
   public boolean isCancellable()
   {
-    return true;
+    return server instanceof CancellableI;
   }
 
   @Override
   public void cancelJob()
   {
+    // TODO decide if when some jobs are not cancellable to shut down the thread
+    // anyhow ?
     if (!jobComplete && jobs != null)
     {
       boolean cancelled = true;
@@ -549,13 +176,11 @@ class MsaWSThread extends AWS2Thread implements WSClientI
           String cancelledMessage = "";
           try
           {
-            boolean cancelledJob = server.cancelJob(jobs[job].getJobId());
-            if (true) // cancelledJob || true)
+            CancellableI service = (CancellableI) server;
+            boolean cancelledJob = service.cancel((WsJob) jobs[job]);
+            if (cancelledJob)
             {
               // CANCELLED_JOB
-              // if the Jaba server indicates the job can't be cancelled, its
-              // because its running on the server's local execution engine
-              // so we just close the window anyway.
               cancelledMessage = "Job cancelled.";
               ((MsaWSJob) jobs[job]).cancel(); // TODO: refactor to avoid this
                                                // ugliness -
@@ -615,42 +240,8 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     // this is standard code, but since the interface doesn't comprise of a
     // basic one that implements (getJobStatus, pullExecStatistics) we have to
     // repeat the code for all jw2s services.
-    j.setjobStatus(server.getJobStatus(job.getJobId()));
-    updateJobProgress(j);
-  }
-
-  /**
-   * 
-   * @param j
-   * @return true if more job progress data was available
-   * @throws Exception
-   */
-  protected boolean updateJobProgress(MsaWSJob j) throws Exception
-  {
-    StringBuffer response = j.jobProgress;
-    long lastchunk = j.getLastChunk();
-    boolean changed = false;
-    do
-    {
-      j.setLastChunk(lastchunk);
-      ChunkHolder chunk = server.pullExecStatistics(j.getJobId(),
-              lastchunk);
-      if (chunk != null)
-      {
-        changed |= chunk.getChunk().length() > 0;
-        response.append(chunk.getChunk());
-        lastchunk = chunk.getNextPosition();
-        try
-        {
-          Thread.sleep(50);
-        } catch (InterruptedException x)
-        {
-        }
-        ;
-      }
-      ;
-    } while (lastchunk >= 0 && j.getLastChunk() != lastchunk);
-    return changed;
+    server.updateStatus(j);
+    server.updateJobProgress(j);
   }
 
   @Override
@@ -679,26 +270,37 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     if (j.seqs == null || j.seqs.size() == 0)
     {
       // special case - selection consisted entirely of empty sequences...
-      j.setjobStatus(JobStatus.FINISHED);
+      j.setState(JobState.FINISHED);
       j.setStatus(MessageManager.getString("label.empty_alignment_job"));
     }
     try
     {
       j.addInitialStatus(); // list the presets/parameters used for the job in
                             // status
-      if (j.isPresetJob())
+      try
       {
-        j.setJobId(server.presetAlign(j.seqs, j.getServerPreset()));
-      }
-      else if (j.hasArguments())
-      {
-        j.setJobId(server.customAlign(j.seqs, j.getJabaArguments()));
-      }
-      else
+        JobId jobHandle = server.align(j.seqs, j.getPreset(),
+                j.getArguments());
+        if (jobHandle != null)
+        {
+          j.setJobHandle(jobHandle);
+        }
+
+      } catch (Throwable throwable)
       {
-        j.setJobId(server.align(j.seqs));
+        if (!server.handleSubmitError(throwable, j, wsInfo))
+        {
+          if (throwable instanceof Exception)
+          {
+            throw ((Exception) throwable);
+          }
+          if (throwable instanceof Error)
+          {
+            throw ((Error) throwable);
+          }
+        }
       }
-
+      ///// generic
       if (j.getJobId() != null)
       {
         j.setSubmitted(true);
@@ -713,40 +315,11 @@ class MsaWSThread extends AWS2Thread implements WSClientI
                 new String[]
                 { WsUrl }));
       }
-    } catch (compbio.metadata.UnsupportedRuntimeException _lex)
-    {
-      lex = _lex;
-      wsInfo.appendProgressText(MessageManager.formatMessage(
-              "info.job_couldnt_be_run_server_doesnt_support_program",
-              new String[]
-              { _lex.getMessage() }));
-      wsInfo.warnUser(_lex.getMessage(),
-              MessageManager.getString("warn.service_not_supported"));
-      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
-      wsInfo.setStatus(j.getJobnum(),
-              WebserviceInfo.STATE_STOPPED_SERVERERROR);
-    } catch (compbio.metadata.LimitExceededException _lex)
-    {
-      lex = _lex;
-      wsInfo.appendProgressText(MessageManager.formatMessage(
-              "info.job_couldnt_be_run_exceeded_hard_limit", new String[]
-              { _lex.getMessage() }));
-      wsInfo.warnUser(_lex.getMessage(),
-              MessageManager.getString("warn.input_is_too_big"));
-      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
-      wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
-    } catch (compbio.metadata.WrongParameterException _lex)
-    {
-      lex = _lex;
-      wsInfo.warnUser(_lex.getMessage(),
-              MessageManager.getString("warn.invalid_job_param_set"));
-      wsInfo.appendProgressText(MessageManager.formatMessage(
-              "info.job_couldnt_be_run_incorrect_param_setting",
-              new String[]
-              { _lex.getMessage() }));
-      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
-      wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
-    } catch (Error e)
+    }
+    //// jabaws specific
+
+    //// generic
+    catch (Error e)
     {
       // For unexpected errors
       System.err.println(WebServiceName
@@ -802,7 +375,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI
           {
             try
             {
-              jpchanged = updateJobProgress(msjob);
+              jpchanged = server.updateJobProgress(msjob);
               jpex = false;
               if (jpchanged)
               {
@@ -843,25 +416,18 @@ class MsaWSThread extends AWS2Thread implements WSClientI
             System.out.println("*** End of status");
 
           }
+          ///// jabaws specific(ish) Get Result from Server when available
           try
           {
-            msjob.alignment = server.getResult(msjob.getJobId());
-          } catch (compbio.metadata.ResultNotAvailableException e)
-          {
-            // job has failed for some reason - probably due to invalid
-            // parameters
-            Cache.log.debug(
-                    "Results not available for finished job - marking as broken job.",
-                    e);
-            msjob.jobProgress.append(
-                    "\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n"
-                            + e.getLocalizedMessage());
-            msjob.setjobStatus(JobStatus.FAILED);
+            msjob.alignment = server.getAlignmentFor(msjob.getJobHandle());
           } catch (Exception e)
           {
-            Cache.log.error("Couldn't get Alignment for job.", e);
-            // TODO: Increment count and retry ?
-            msjob.setjobStatus(JobStatus.UNDEFINED);
+            if (!server.handleCollectionException(e, msjob, wsInfo))
+            {
+              Cache.log.error("Couldn't get Alignment for job.", e);
+              // TODO: Increment count and retry ?
+              msjob.setState(JobState.SERVERERROR);
+            }
           }
         }
         finalState.updateJobPanelState(wsInfo, OutputHeader, jobs[j]);
@@ -869,19 +435,6 @@ class MsaWSThread extends AWS2Thread implements WSClientI
                 && jobs[j].hasResults())
         {
           results++;
-          compbio.data.sequence.Alignment alignment = ((MsaWSJob) jobs[j]).alignment;
-          if (alignment != null)
-          {
-            // server.close(jobs[j].getJobnum());
-            // wsInfo.appendProgressText(jobs[j].getJobnum(),
-            // "\nAlignment Object Method Notes\n");
-            // wsInfo.appendProgressText(jobs[j].getJobnum(),
-            // "Calculated with
-            // "+alignment.getMetadata().getProgram().toString());
-            // JBPNote The returned files from a webservice could be
-            // hidden behind icons in the monitor window that,
-            // when clicked, pop up their corresponding data
-          }
         }
       }
     } catch (Exception ex)
@@ -931,7 +484,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 +534,6 @@ class MsaWSThread extends AWS2Thread implements WSClientI
     if (newFrame)
     {
       displayInNewFrame(al, alorders, hidden);
-
     }
     else
     {
@@ -1077,7 +629,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;
diff --git a/src/jalview/ws/gui/WsJob.java b/src/jalview/ws/gui/WsJob.java
new file mode 100644 (file)
index 0000000..05379d7
--- /dev/null
@@ -0,0 +1,176 @@
+/**
+ * 
+ */
+package jalview.ws.gui;
+
+import jalview.ws.AWsJob;
+
+/**
+ * Bean that holds state for a job
+ * 
+ * @author jprocter
+ *
+ */
+public class WsJob extends AWsJob
+{
+
+  public enum JobState
+  {
+    INVALID, READY, SUBMITTED, QUEUED, RUNNING, FINISHED, BROKEN, FAILED,
+    UNKNOWN, SERVERERROR, CANCELLED;
+  };
+
+  JobState state = JobState.UNKNOWN;
+
+  boolean hasResults = false, validInput = false;
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#hasResults()
+   */
+  @Override
+  public boolean hasResults()
+  {
+    return hasResults;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#hasValidInput()
+   */
+  @Override
+  public boolean hasValidInput()
+  {
+    return validInput;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isRunning()
+   */
+  @Override
+  public boolean isRunning()
+  {
+    return JobState.RUNNING.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isQueued()
+   */
+  @Override
+  public boolean isQueued()
+  {
+    return JobState.QUEUED.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isFinished()
+   */
+  @Override
+  public boolean isFinished()
+  {
+    // TODO isSubjobComplete and finished flags mean same thing ?
+    return JobState.FINISHED.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isFailed()
+   */
+  @Override
+  public boolean isFailed()
+  {
+    return JobState.FAILED.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isBroken()
+   */
+  @Override
+  public boolean isBroken()
+  {
+    return JobState.BROKEN.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#isServerError()
+   */
+  @Override
+  public boolean isServerError()
+  {
+    return JobState.SERVERERROR.equals(state);
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#hasStatus()
+   */
+  @Override
+  public boolean hasStatus()
+  {
+    return status != null && status.length() > 0;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#getStatus()
+   */
+  @Override
+  public String getStatus()
+  {
+    return status;
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#hasResponse()
+   */
+  @Override
+  public boolean hasResponse()
+  {
+    // TODO Auto-generated method stub
+    return hasStatus();
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#clearResponse()
+   */
+  @Override
+  public void clearResponse()
+  {
+    status = "";
+  }
+
+  /* (non-Javadoc)
+   * @see jalview.ws.AWsJob#getState()
+   */
+  @Override
+  public String getState()
+  {
+    return state.toString();
+  }
+
+  /**
+   * @return the current JobState
+   */
+  public JobState getJobState()
+  {
+    return state;
+  }
+
+  /**
+   * set the job state
+   * 
+   * @param state
+   */
+  public void setState(JobState state)
+  {
+    this.state = state;
+  }
+
+  String status = "";
+
+  /**
+   * Set the log for this job
+   * 
+   * @parag log
+   */
+  public void setStatus(String log)
+  {
+    status = log;
+
+  }
+
+}
index 4a09625..e627699 100644 (file)
@@ -51,8 +51,6 @@ public class MsaWSClient extends WS1Client
    */
   ext.vamsas.MuscleWS server;
 
-  AlignFrame alignFrame;
-
   /**
    * Creates a new MsaWSClient object that uses a service given by an externally
    * retrieved ServiceHandle
index 006f014..7b3df82 100644 (file)
@@ -36,7 +36,6 @@ import jalview.ws.AWsJob;
 import jalview.ws.JobStateSummary;
 import jalview.ws.WSClientI;
 
-import java.util.Hashtable;
 import java.util.Vector;
 
 import vamsas.objects.simple.MsaResult;
@@ -78,8 +77,6 @@ class MsaWSThread extends JWS1Thread implements WSClientI
 
     }
 
-    Hashtable SeqNames = new Hashtable();
-
     Vector emptySeqs = new Vector();
 
     /**
index 53338d3..49de37e 100644 (file)
@@ -56,8 +56,6 @@ public class SeqSearchWSClient extends WS1Client
    */
   ext.vamsas.SeqSearchI server;
 
-  AlignFrame alignFrame;
-
   /**
    * Creates a new MsaWSClient object that uses a service given by an externally
    * retrieved ServiceHandle
index 761b758..2f2bf2c 100644 (file)
@@ -37,7 +37,6 @@ import jalview.ws.JobStateSummary;
 import jalview.ws.WSClientI;
 
 import java.util.HashMap;
-import java.util.Hashtable;
 import java.util.Map;
 import java.util.Vector;
 
@@ -77,8 +76,6 @@ class SeqSearchWSThread extends JWS1Thread implements WSClientI
 
     }
 
-    Hashtable SeqNames = new Hashtable();
-
     Vector emptySeqs = new Vector();
 
     /**
index 327864a..ddd69a7 100644 (file)
@@ -24,6 +24,7 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.gui.AlignFrame;
 import jalview.util.MessageManager;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 import jalview.ws.uimodel.AlignAnalysisUIText;
 
@@ -35,13 +36,12 @@ import java.util.TreeSet;
 
 import compbio.data.sequence.FastaSequence;
 import compbio.data.sequence.Score;
-import compbio.metadata.Argument;
 
 public class AAConClient extends JabawsCalcWorker
 {
 
   public AAConClient(Jws2Instance service, AlignFrame alignFrame,
-          WsParamSetI preset, List<Argument> paramset)
+          WsParamSetI preset, List<ArgumentI> paramset)
   {
     super(service, alignFrame, preset, paramset);
     submitGaps = true;
index a1b8e7a..91db7c3 100644 (file)
@@ -30,6 +30,7 @@ import jalview.gui.AlignFrame;
 import jalview.schemes.FeatureColour;
 import jalview.util.ColorUtils;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.awt.Color;
@@ -44,7 +45,6 @@ import compbio.data.sequence.FastaSequence;
 import compbio.data.sequence.Range;
 import compbio.data.sequence.Score;
 import compbio.data.sequence.ScoreManager.ScoreHolder;
-import compbio.metadata.Argument;
 
 public class AADisorderClient extends JabawsCalcWorker
 {
@@ -62,12 +62,12 @@ public class AADisorderClient extends JabawsCalcWorker
   AlignFrame af;
 
   public AADisorderClient(Jws2Instance sh, AlignFrame alignFrame,
-          WsParamSetI thePreset, List<Argument> paramset)
+          WsParamSetI thePreset, List<ArgumentI> paramset)
   {
     super(sh, alignFrame, thePreset, paramset);
     af = alignFrame;
-    typeName = sh.action;
-    methodName = sh.serviceType;
+    typeName = sh.getAction();
+    methodName = sh.getName();
 
     submitGaps = false;
     alignedSeqs = false;
@@ -169,9 +169,9 @@ public class AADisorderClient extends JabawsCalcWorker
     if (immediate || !calcMan.isWorking(this) && scoremanager != null)
     {
       Map<String, String[]> featureTypeMap = featureMap
-              .get(service.serviceType);
+              .get(service.getName());
       Map<String, Map<String, Object>> annotTypeMap = annotMap
-              .get(service.serviceType);
+              .get(service.getName());
       boolean dispFeatures = false;
       Map<String, Object> fc = new Hashtable<>();
       List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
@@ -265,9 +265,9 @@ public class AADisorderClient extends JabawsCalcWorker
               String typename, calcName;
               AlignmentAnnotation annot = createAnnotationRowsForScores(
                       ourAnnot,
-                      typename = service.serviceType + " ("
+                      typename = service.getName() + " ("
                               + scr.getMethod() + ")",
-                      calcName = service.getServiceTypeURI() + "/"
+                      calcName = service.getNameURI() + "/"
                               + scr.getMethod(),
                       aseq, base + 1, scr);
               annot.graph = AlignmentAnnotation.LINE_GRAPH;
index dd64e77..1a361c4 100644 (file)
@@ -36,6 +36,7 @@ import jalview.workers.AlignCalcWorker;
 import jalview.ws.jws2.dm.AAConSettings;
 import jalview.ws.jws2.dm.JabaWsParamSet;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.util.ArrayList;
@@ -44,7 +45,6 @@ import java.util.List;
 import java.util.Map;
 
 import compbio.data.sequence.FastaSequence;
-import compbio.metadata.Argument;
 import compbio.metadata.ChunkHolder;
 import compbio.metadata.JobStatus;
 import compbio.metadata.JobSubmissionException;
@@ -58,7 +58,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
 
   protected WsParamSetI preset;
 
-  protected List<Argument> arguments;
+  protected List<ArgumentI> arguments;
 
   protected IProgressIndicator guiProgress;
 
@@ -78,10 +78,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
     {
       ((jalview.gui.AlignViewport) alignViewport).setCalcIdSettingsFor(
               getCalcId(),
-              new AAConSettings(true, service, this.preset,
-                      (arguments != null)
-                              ? JabaParamStore.getJwsArgsfromJaba(arguments)
-                              : null),
+              new AAConSettings(true, service, this.preset, arguments),
               true);
     }
   }
@@ -98,7 +95,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
     return preset;
   }
 
-  public List<Argument> getArguments()
+  public List<ArgumentI> getArguments()
   {
     return arguments;
   }
@@ -112,7 +109,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
    * @param newarguments
    */
   public void updateParameters(final WsParamSetI newpreset,
-          final List<Argument> newarguments)
+          final List<ArgumentI> newarguments)
   {
     preset = newpreset;
     arguments = newarguments;
@@ -129,7 +126,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
     }
     if (arguments != null && arguments.size() > 0)
     {
-      for (Argument rg : arguments)
+      for (Object rg : JabaParamStore.getJabafromJwsArgs(arguments))
       {
         if (Option.class.isAssignableFrom(rg.getClass()))
         {
@@ -168,7 +165,7 @@ public abstract class AbstractJabaCalcWorker extends AlignCalcWorker
   }
 
   public AbstractJabaCalcWorker(Jws2Instance service, AlignFrame alignFrame,
-          WsParamSetI preset, List<Argument> paramset)
+          WsParamSetI preset, List<ArgumentI> paramset)
   {
     this(alignFrame.getCurrentView(), alignFrame.alignPanel);
     this.guiProgress = alignFrame;
index 10ec812..0257a76 100644 (file)
@@ -47,7 +47,7 @@ import compbio.metadata.RunnerConfig;
 public class JabaParamStore implements ParamDatastoreI
 {
 
-  Hashtable<String, JabaWsParamSet> editedParams = new Hashtable<String, JabaWsParamSet>();
+  Hashtable<String, JabaWsParamSet> editedParams = new Hashtable<>();
 
   private Jws2Instance service;
 
@@ -101,7 +101,7 @@ public class JabaParamStore implements ParamDatastoreI
     List<WsParamSetI> prefs = new ArrayList();
     if (servicePresets == null)
     {
-      servicePresets = new Hashtable<String, JabaPreset>();
+      servicePresets = new Hashtable<>();
       PresetManager prman;
       if ((prman = service.getPresets()) != null)
       {
@@ -148,8 +148,8 @@ public class JabaParamStore implements ParamDatastoreI
   public static List<ArgumentI> getJwsArgsfromJaba(List jabargs,
           boolean sortByOpt)
   {
-    List<ArgumentI> rgs = new ArrayList<ArgumentI>();
-    List<String> rgnames = new ArrayList<String>();
+    List<ArgumentI> rgs = new ArrayList<>();
+    List<String> rgnames = new ArrayList<>();
     for (Object rg : jabargs)
     {
       ArgumentI narg = null;
@@ -309,7 +309,7 @@ public class JabaParamStore implements ParamDatastoreI
     boolean found = false;
     for (String url : urls)
     {
-      if (service.getServiceTypeURI().equals(url)
+      if (service.getNameURI().equals(url)
               || service.getUri().equalsIgnoreCase(url))
       {
         found = true;
@@ -334,7 +334,7 @@ public class JabaParamStore implements ParamDatastoreI
     wsp.setDescription(descr);
     wsp.setApplicableUrls(urls.clone());
 
-    List<String> lines = new ArrayList<String>();
+    List<String> lines = new ArrayList<>();
     StringTokenizer st = new StringTokenizer(parameterfile, "\n");
     while (st.hasMoreTokens())
     {
index 981b288..b6a18dd 100644 (file)
@@ -100,4 +100,9 @@ public class JabaPreset implements WsParamSetI
     throw new Error(MessageManager
             .getString("error.cannot_set_params_for_ws_preset"));
   }
+
+  public Preset getJabaPreset()
+  {
+    return p;
+  }
 }
diff --git a/src/jalview/ws/jws2/JabaWsParamTest.java b/src/jalview/ws/jws2/JabaWsParamTest.java
new file mode 100644 (file)
index 0000000..8c57529
--- /dev/null
@@ -0,0 +1,262 @@
+package jalview.ws.jws2;
+
+import jalview.gui.WsJobParameters;
+import jalview.util.MessageManager;
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+
+import java.awt.BorderLayout;
+import java.awt.event.WindowEvent;
+import java.awt.event.WindowListener;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+
+import compbio.metadata.Option;
+import compbio.metadata.Parameter;
+import compbio.metadata.Preset;
+import compbio.metadata.PresetManager;
+
+public class JabaWsParamTest
+{
+
+  /**
+   * testing method - grab a service and parameter set and show the window
+   * 
+   * @param args
+   */
+  public static void main(String[] args)
+  {
+    jalview.ws.jws2.Jws2Discoverer disc = jalview.ws.jws2.Jws2Discoverer
+            .getDiscoverer();
+    int p = 0;
+    if (args.length > 0)
+    {
+      Vector<String> services = new Vector<>();
+      services.addElement(args[p++]);
+      Jws2Discoverer.getDiscoverer().setServiceUrls(services);
+    }
+    try
+    {
+      disc.run();
+    } catch (Exception e)
+    {
+      System.err.println("Aborting. Problem discovering services.");
+      e.printStackTrace();
+      return;
+    }
+    Jws2Instance lastserv = null;
+    for (Jws2Instance service : disc.getServices())
+    {
+      lastserv = service;
+      if (p >= args.length || service.getName().equalsIgnoreCase(args[p]))
+      {
+        if (lastserv != null)
+        {
+          List<Preset> prl = null;
+          Preset pr = null;
+          if (++p < args.length)
+          {
+            PresetManager prman = lastserv.getPresets();
+            if (prman != null)
+            {
+              pr = prman.getPresetByName(args[p]);
+              if (pr == null)
+              {
+                // just grab the last preset.
+                prl = prman.getPresets();
+              }
+            }
+          }
+          else
+          {
+            PresetManager prman = lastserv.getPresets();
+            if (prman != null)
+            {
+              prl = prman.getPresets();
+            }
+          }
+          Iterator<Preset> en = (prl == null) ? null : prl.iterator();
+          while (en != null && en.hasNext())
+          {
+            if (en != null)
+            {
+              if (!en.hasNext())
+              {
+                en = prl.iterator();
+              }
+              pr = en.next();
+            }
+            {
+              System.out.println("Testing opts dupes for "
+                      + lastserv.getUri() + " : " + lastserv.getActionText()
+                      + ":" + pr.getName());
+              List<Option> rg = lastserv.getRunnerConfig().getOptions();
+              for (Option o : rg)
+              {
+                try
+                {
+                  Option cpy = jalview.ws.jws2.ParameterUtils.copyOption(o);
+                } catch (Exception e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                } catch (Error e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                }
+              }
+            }
+            {
+              System.out.println("Testing param dupes:");
+              List<Parameter> rg = lastserv.getRunnerConfig()
+                      .getParameters();
+              for (Parameter o : rg)
+              {
+                try
+                {
+                  Parameter cpy = jalview.ws.jws2.ParameterUtils
+                          .copyParameter(o);
+                } catch (Exception e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                } catch (Error e)
+                {
+                  System.err.println("Failed to copy " + o.getName());
+                  e.printStackTrace();
+                }
+              }
+            }
+            {
+              System.out.println("Testing param write:");
+              List<String> writeparam = null, readparam = null;
+              try
+              {
+                writeparam = jalview.ws.jws2.ParameterUtils
+                        .writeParameterSet(
+                                pr.getArguments(lastserv.getRunnerConfig()),
+                                " ");
+                System.out.println("Testing param read :");
+                List<Option> pset = jalview.ws.jws2.ParameterUtils
+                        .processParameters(writeparam,
+                                lastserv.getRunnerConfig(), " ");
+                readparam = jalview.ws.jws2.ParameterUtils
+                        .writeParameterSet(pset, " ");
+                Iterator<String> o = pr.getOptions().iterator(),
+                        s = writeparam.iterator(), t = readparam.iterator();
+                boolean failed = false;
+                while (s.hasNext() && t.hasNext())
+                {
+                  String on = o.next(), sn = s.next(), st = t.next();
+                  if (!sn.equals(st))
+                  {
+                    System.out.println(
+                            "Original was " + on + " Phase 1 wrote " + sn
+                                    + "\tPhase 2 wrote " + st);
+                    failed = true;
+                  }
+                }
+                if (failed)
+                {
+                  System.out.println(
+                          "Original parameters:\n" + pr.getOptions());
+                  System.out.println(
+                          "Wrote parameters in first set:\n" + writeparam);
+                  System.out.println(
+                          "Wrote parameters in second set:\n" + readparam);
+
+                }
+              } catch (Exception e)
+              {
+                e.printStackTrace();
+              }
+            }
+            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() }));
+            JPanel cont = new JPanel(new BorderLayout());
+            pgui.validate();
+            cont.setPreferredSize(pgui.getPreferredSize());
+            cont.add(pgui, BorderLayout.CENTER);
+            jf.setLayout(new BorderLayout());
+            jf.add(cont, BorderLayout.CENTER);
+            jf.validate();
+            final Thread thr = Thread.currentThread();
+            jf.addWindowListener(new WindowListener()
+            {
+
+              @Override
+              public void windowActivated(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowClosed(WindowEvent e)
+              {
+              }
+
+              @Override
+              public void windowClosing(WindowEvent e)
+              {
+                thr.interrupt();
+
+              }
+
+              @Override
+              public void windowDeactivated(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowDeiconified(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowIconified(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+              @Override
+              public void windowOpened(WindowEvent e)
+              {
+                // TODO Auto-generated method stub
+
+              }
+
+            });
+            jf.setVisible(true);
+            boolean inter = false;
+            while (!inter)
+            {
+              try
+              {
+                Thread.sleep(10000);
+              } catch (Exception e)
+              {
+                inter = true;
+              }
+              ;
+            }
+            jf.dispose();
+          }
+        }
+      }
+    }
+  }
+
+}
index fc36205..c70e721 100644 (file)
@@ -26,6 +26,7 @@ import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.util.MessageManager;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.util.Iterator;
@@ -34,7 +35,6 @@ import java.util.List;
 import compbio.data.msa.SequenceAnnotation;
 import compbio.data.sequence.Score;
 import compbio.data.sequence.ScoreManager;
-import compbio.metadata.Argument;
 import compbio.metadata.ChunkHolder;
 import compbio.metadata.JobStatus;
 import compbio.metadata.JobSubmissionException;
@@ -50,7 +50,7 @@ public abstract class JabawsCalcWorker extends AbstractJabaCalcWorker
   protected ScoreManager scoremanager;
 
   public JabawsCalcWorker(Jws2Instance service, AlignFrame alignFrame,
-          WsParamSetI preset, List<Argument> paramset)
+          WsParamSetI preset, List<ArgumentI> paramset)
   {
     super(service, alignFrame, preset, paramset);
     aaservice = (SequenceAnnotation) service.service;
index ee36d4a..5ccef8a 100644 (file)
@@ -28,6 +28,7 @@ import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.util.MessageManager;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.util.Iterator;
@@ -36,7 +37,6 @@ import java.util.List;
 import compbio.data.msa.MsaWS;
 import compbio.data.sequence.Alignment;
 import compbio.data.sequence.Score;
-import compbio.metadata.Argument;
 import compbio.metadata.ChunkHolder;
 import compbio.metadata.JobStatus;
 import compbio.metadata.JobSubmissionException;
@@ -60,7 +60,7 @@ public abstract class JabawsMsaInterfaceAlignCalcWorker
 
   public JabawsMsaInterfaceAlignCalcWorker(Jws2Instance service,
           AlignFrame alignFrame, WsParamSetI preset,
-          List<Argument> paramset)
+          List<ArgumentI> paramset)
   {
     this(alignFrame.getCurrentView(), alignFrame.alignPanel);
     this.guiProgress = alignFrame;
index 0f1a25e..1c13891 100644 (file)
@@ -23,14 +23,13 @@ package jalview.ws.jws2;
 import jalview.api.AlignCalcWorkerI;
 import jalview.bin.Cache;
 import jalview.gui.AlignFrame;
-import jalview.gui.Desktop;
 import jalview.gui.JvSwingUtils;
-import jalview.gui.WebserviceInfo;
-import jalview.gui.WsJobParameters;
 import jalview.util.MessageManager;
+import jalview.ws.api.ServiceWithParameters;
 import jalview.ws.jws2.dm.AAConSettings;
 import jalview.ws.jws2.dm.JabaWsParamSet;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 import jalview.ws.uimodel.AlignAnalysisUIText;
 
@@ -44,8 +43,6 @@ import javax.swing.JMenuItem;
 import javax.swing.event.MenuEvent;
 import javax.swing.event.MenuListener;
 
-import compbio.metadata.Argument;
-
 /**
  * provides metadata for a jabaws2 service instance - resolves names, etc.
  * 
@@ -54,17 +51,10 @@ import compbio.metadata.Argument;
  */
 public abstract class Jws2Client extends jalview.ws.WSClient
 {
-  protected AlignFrame alignFrame;
-
-  protected WsParamSetI preset;
-
-  protected List<Argument> paramset;
-
   public Jws2Client(AlignFrame _alignFrame, WsParamSetI preset,
-          List<Argument> arguments)
+          List<ArgumentI> arguments)
   {
-    alignFrame = _alignFrame;
-    this.preset = preset;
+    super(_alignFrame, preset, arguments);
     if (preset != null)
     {
       if (!((preset instanceof JabaPreset)
@@ -85,81 +75,16 @@ public abstract class Jws2Client extends jalview.ws.WSClient
     }
     else
     {
-      // just provided with a bunch of arguments
-      this.paramset = arguments;
+      // TODO: verify that paramset is compatible with the service being
+      // contacted
     }
   }
 
-  boolean processParams(Jws2Instance sh, boolean editParams)
-  {
-    return processParams(sh, editParams, false);
-  }
-
-  protected boolean processParams(Jws2Instance sh, boolean editParams,
-          boolean adjustingExisting)
-  {
-
-    if (editParams)
-    {
-      if (sh.paramStore == null)
-      {
-        sh.paramStore = new JabaParamStore(sh,
-                Desktop.getUserParameterStore());
-      }
-      WsJobParameters jobParams = (preset == null && paramset != null
-              && paramset.size() > 0)
-                      ? new WsJobParameters(null, sh, null, paramset)
-                      : new WsJobParameters(sh, preset);
-      if (adjustingExisting)
-      {
-        jobParams.setName(MessageManager
-                .getString("label.adjusting_parameters_for_calculation"));
-      }
-      if (!jobParams.showRunDialog())
-      {
-        return false;
-      }
-      WsParamSetI prset = jobParams.getPreset();
-      if (prset == null)
-      {
-        paramset = jobParams.isServiceDefaults() ? null
-                : JabaParamStore
-                        .getJabafromJwsArgs(jobParams.getJobParams());
-        this.preset = null;
-      }
-      else
-      {
-        this.preset = prset; // ((JabaPreset) prset).p;
-        paramset = null; // no user supplied parameters.
-      }
-    }
-    return true;
-
-  }
-
   public Jws2Client()
   {
     // anonymous constructor - used for headless method calls only
   }
 
-  protected WebserviceInfo setWebService(Jws2Instance serv, boolean b)
-  {
-    // serviceHandle = serv;
-    String serviceInstance = serv.action; // serv.service.getClass().getName();
-    WebServiceName = serv.serviceType;
-    WebServiceJobTitle = serv.getActionText();
-    WsURL = serv.hosturl;
-    if (!b)
-    {
-      return new WebserviceInfo(WebServiceJobTitle,
-              WebServiceJobTitle + " using service hosted at "
-                      + serv.hosturl + "\n"
-                      + (serv.description != null ? serv.description : ""),
-              false);
-    }
-    return null;
-  }
-
   /*
    * Jws2Instance serviceHandle; (non-Javadoc)
    * 
@@ -178,13 +103,15 @@ public abstract class Jws2Client extends jalview.ws.WSClient
    * @param service
    * @param alignFrame
    */
-  abstract void attachWSMenuEntry(JMenu wsmenu, final Jws2Instance service,
+  abstract void attachWSMenuEntry(JMenu wsmenu,
+          final ServiceWithParameters service,
           final AlignFrame alignFrame);
 
-  protected boolean registerAAConWSInstance(final JMenu wsmenu,
-          final Jws2Instance service, final AlignFrame alignFrame)
+  static boolean registerAAConWSInstance(final JMenu wsmenu,
+          final ServiceWithParameters service, final AlignFrame alignFrame)
   {
-    final AlignAnalysisUIText aaui = service.getAlignAnalysisUI(); // null ; //
+    Jws2Instance jaba_service = (Jws2Instance) service;
+    final AlignAnalysisUIText aaui = jaba_service.getAlignAnalysisUI(); // null ; //
                                                                    // AlignAnalysisUIText.aaConGUI.get(service.serviceType.toString());
     if (aaui == null)
     {
@@ -214,7 +141,7 @@ public abstract class Jws2Client extends jalview.ws.WSClient
       {
         AbstractJabaCalcWorker worker = (AbstractJabaCalcWorker) aaconClient
                 .get(0);
-        if (!worker.service.hosturl.equals(service.hosturl))
+        if (!worker.service.getHostURL().equals(service.getHostURL()))
         {
           // javax.swing.SwingUtilities.invokeLater(new Runnable()
           {
@@ -222,7 +149,7 @@ public abstract class Jws2Client extends jalview.ws.WSClient
             // public void run()
             {
               removeCurrentAAConWorkerFor(aaui, alignFrame);
-              buildCurrentAAConWorkerFor(aaui, alignFrame, service);
+              buildCurrentAAConWorkerFor(aaui, alignFrame, jaba_service);
             }
           } // );
         }
@@ -365,10 +292,11 @@ public abstract class Jws2Client extends jalview.ws.WSClient
     else
     {
       if (service != null
-              && !fave.getService().hosturl.equals(service.hosturl))
+              && !fave.getService().getHostURL()
+                      .equals(service.getHostURL()))
       {
-        Cache.log.debug("Changing AACon service to " + service.hosturl
-                + " from " + fave.getService().hosturl);
+        Cache.log.debug("Changing AACon service to " + service.getHostURL()
+                + " from " + fave.getService().getHostURL());
         fave.setService(service);
       }
     }
@@ -386,12 +314,12 @@ public abstract class Jws2Client extends jalview.ws.WSClient
   {
     if (service != null)
     {
-      if (!service.serviceType.toString()
+      if (!service.getServiceType()
               .equals(compbio.ws.client.Services.AAConWS.toString()))
       {
         Cache.log.warn(
                 "Ignoring invalid preferred service for AACon calculations (service type was "
-                        + service.serviceType + ")");
+                        + service.getServiceType() + ")");
         service = null;
       }
       else
index 5319eab..e4ff459 100644 (file)
@@ -178,7 +178,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     running = true;
 
     // first set up exclusion list if needed
-    final Set<String> ignoredServices = new HashSet<String>();
+    final Set<String> ignoredServices = new HashSet<>();
     for (String ignored : Cache
             .getDefault("IGNORED_JABAWS_SERVICETYPES", "").split("\\|"))
     {
@@ -217,9 +217,9 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     {
       validServiceUrls.removeAllElements();
     }
-    ArrayList<String> svctypes = new ArrayList<String>();
+    ArrayList<String> svctypes = new ArrayList<>();
 
-    List<JabaWsServerQuery> qrys = new ArrayList<JabaWsServerQuery>();
+    List<JabaWsServerQuery> qrys = new ArrayList<>();
     for (final String jwsserver : getServiceUrls())
     {
       JabaWsServerQuery squery = new JabaWsServerQuery(this, jwsserver);
@@ -281,14 +281,14 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
         for (Jws2Instance svc : services)
         {
           svcs[ipos] = svc;
-          spos[ipos++] = 1000 * svcUrls.indexOf(svc.getHost()) + 1
-                  + svctypes.indexOf(svc.serviceType);
+          spos[ipos++] = 1000 * svcUrls.indexOf(svc.getHostURL()) + 1
+                  + svctypes.indexOf(svc.getName());
         }
         jalview.util.QuickSort.sort(spos, svcs);
-        services = new Vector<Jws2Instance>();
+        services = new Vector<>();
         for (Jws2Instance svc : svcs)
         {
-          if (!ignoredServices.contains(svc.serviceType))
+          if (!ignoredServices.contains(svc.getName()))
           {
             services.add(svc);
           }
@@ -312,7 +312,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     if (services == null)
     {
-      services = new Vector<Jws2Instance>();
+      services = new Vector<>();
     }
     System.out.println(
             "Discovered service: " + jwsservers + " " + service.toString());
@@ -329,7 +329,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     service.hasParameters();
     if (validServiceUrls == null)
     {
-      validServiceUrls = new Vector<String>();
+      validServiceUrls = new Vector<>();
     }
     validServiceUrls.add(jwsservers);
   }
@@ -363,13 +363,14 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
      * for moment we keep them separate.
      */
     JMenu atpoint;
-    List<Jws2Instance> enumerableServices = new ArrayList<Jws2Instance>();
+    List<Jws2Instance> enumerableServices = new ArrayList<>();
     // jws2al.removeAll();
-    Map<String, Jws2Instance> preferredHosts = new HashMap<String, Jws2Instance>();
-    Map<String, List<Jws2Instance>> alternates = new HashMap<String, List<Jws2Instance>>();
+    Map<String, Jws2Instance> preferredHosts = new HashMap<>();
+    Map<String, List<Jws2Instance>> alternates = new HashMap<>();
     for (Jws2Instance service : services.toArray(new Jws2Instance[0]))
     {
-      if (!isRecalculable(service.action))
+      // TODO: check this behaves with refactored serviceType to getName
+      if (!isRecalculable(service.getName()))
       {
         // add 'one shot' services to be displayed using the classic menu
         // structure
@@ -377,28 +378,28 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       }
       else
       {
-        if (!preferredHosts.containsKey(service.serviceType))
+        if (!preferredHosts.containsKey(service.getName()))
         {
           Jws2Instance preferredInstance = getPreferredServiceFor(
-                  alignFrame, service.serviceType);
+                  alignFrame, service.getName());
           if (preferredInstance != null)
           {
-            preferredHosts.put(service.serviceType, preferredInstance);
+            preferredHosts.put(service.getName(), preferredInstance);
           }
           else
           {
-            preferredHosts.put(service.serviceType, service);
+            preferredHosts.put(service.getName(), service);
           }
         }
-        List<Jws2Instance> ph = alternates.get(service.serviceType);
-        if (preferredHosts.get(service.serviceType) != service)
+        List<Jws2Instance> ph = alternates.get(service.getName());
+        if (preferredHosts.get(service.getName()) != service)
         {
           if (ph == null)
           {
-            ph = new ArrayList<Jws2Instance>();
+            ph = new ArrayList<>();
           }
           ph.add(service);
-          alternates.put(service.serviceType, ph);
+          alternates.put(service.getName(), ph);
         }
       }
 
@@ -409,14 +410,15 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     // and the instantaneous services
     for (final Jws2Instance service : preferredHosts.values())
     {
-      atpoint = JvSwingUtils.findOrCreateMenu(jws2al, service.action);
+      atpoint = JvSwingUtils.findOrCreateMenu(jws2al,
+              service.getServiceType());
       JMenuItem hitm;
       if (atpoint.getItemCount() > 1)
       {
         // previous service of this type already present
         atpoint.addSeparator();
       }
-      atpoint.add(hitm = new JMenuItem(service.getHost()));
+      atpoint.add(hitm = new JMenuItem(service.getHostURL()));
       hitm.setForeground(Color.blue);
       hitm.addActionListener(new ActionListener()
       {
@@ -424,23 +426,23 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
         @Override
         public void actionPerformed(ActionEvent e)
         {
-          Desktop.showUrl(service.getHost());
+          Desktop.showUrl(service.getHostURL());
         }
       });
       hitm.setToolTipText(JvSwingUtils.wrapTooltip(false,
               MessageManager.getString("label.open_jabaws_web_page")));
 
       service.attachWSMenuEntry(atpoint, alignFrame);
-      if (alternates.containsKey(service.serviceType))
+      if (alternates.containsKey(service.getName()))
       {
         atpoint.add(hitm = new JMenu(
                 MessageManager.getString("label.switch_server")));
         hitm.setToolTipText(JvSwingUtils.wrapTooltip(false,
                 MessageManager.getString("label.choose_jabaws_server")));
-        for (final Jws2Instance sv : alternates.get(service.serviceType))
+        for (final Jws2Instance sv : alternates.get(service.getName()))
         {
           JMenuItem itm;
-          hitm.add(itm = new JMenuItem(sv.getHost()));
+          hitm.add(itm = new JMenuItem(sv.getHostURL()));
           itm.setForeground(Color.blue);
           itm.addActionListener(new ActionListener()
           {
@@ -453,8 +455,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
                 @Override
                 public void run()
                 {
-                  setPreferredServiceFor(alignFrame, sv.serviceType,
-                          sv.action, sv);
+                  setPreferredServiceFor(alignFrame, sv.getName(),
+                          sv.getServiceType(), sv);
                   changeSupport.firePropertyChange("services",
                           new Vector<Jws2Instance>(), services);
                 };
@@ -483,18 +485,19 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
      */
     JMenu atpoint;
 
-    List<String> hostLabels = new ArrayList<String>();
-    Hashtable<String, String> lasthostFor = new Hashtable<String, String>();
-    Hashtable<String, ArrayList<Jws2Instance>> hosts = new Hashtable<String, ArrayList<Jws2Instance>>();
-    ArrayList<String> hostlist = new ArrayList<String>();
+    List<String> hostLabels = new ArrayList<>();
+    Hashtable<String, String> lasthostFor = new Hashtable<>();
+    Hashtable<String, ArrayList<Jws2Instance>> hosts = new Hashtable<>();
+    ArrayList<String> hostlist = new ArrayList<>();
     for (Jws2Instance service : enumerableServices)
     {
-      ArrayList<Jws2Instance> hostservices = hosts.get(service.getHost());
+      ArrayList<Jws2Instance> hostservices = hosts
+              .get(service.getHostURL());
       if (hostservices == null)
       {
-        hosts.put(service.getHost(),
-                hostservices = new ArrayList<Jws2Instance>());
-        hostlist.add(service.getHost());
+        hosts.put(service.getHostURL(),
+                hostservices = new ArrayList<>());
+        hostlist.add(service.getHostURL());
       }
       hostservices.add(service);
     }
@@ -506,13 +509,14 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       String sortbytype[] = new String[orderedsvcs.length];
       for (int i = 0; i < sortbytype.length; i++)
       {
-        sortbytype[i] = orderedsvcs[i].serviceType;
+        sortbytype[i] = orderedsvcs[i].getName();
       }
       jalview.util.QuickSort.sort(sortbytype, orderedsvcs);
       for (final Jws2Instance service : orderedsvcs)
       {
-        atpoint = JvSwingUtils.findOrCreateMenu(jws2al, service.action);
-        String type = service.serviceType;
+        atpoint = JvSwingUtils.findOrCreateMenu(jws2al,
+                service.getAction());
+        String type = service.getName();
         if (byhost)
         {
           atpoint = JvSwingUtils.findOrCreateMenu(atpoint, host);
@@ -532,7 +536,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
           }
         }
         if (!byhost && !hostLabels.contains(
-                host + service.serviceType + service.getActionText()))
+                host + service.getName() + service.getActionText()))
         // !hostLabels.contains(host + (bytype ?
         // service.serviceType+service.getActionText() : "")))
         {
@@ -549,8 +553,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
           {
             hostLabels.add(host);
           }
-          if (lasthostFor.get(service.action) == null
-                  || !lasthostFor.get(service.action).equals(host))
+          if (lasthostFor.get(service.getAction()) == null
+                  || !lasthostFor.get(service.getAction()).equals(host))
           {
             atpoint.add(hitm = new JMenuItem(host));
             hitm.setForeground(Color.blue);
@@ -560,16 +564,16 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
               @Override
               public void actionPerformed(ActionEvent e)
               {
-                Desktop.showUrl(service.getHost());
+                Desktop.showUrl(service.getHostURL());
               }
             });
             hitm.setToolTipText(
                     JvSwingUtils.wrapTooltip(true, MessageManager
                             .getString("label.open_jabaws_web_page")));
-            lasthostFor.put(service.action, host);
+            lasthostFor.put(service.getAction(), host);
           }
           hostLabels.add(
-                  host + service.serviceType + service.getActionText());
+                  host + service.getName() + service.getActionText());
         }
 
         service.attachWSMenuEntry(atpoint, alignFrame);
@@ -581,7 +585,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     if (args.length > 0)
     {
-      testUrls = new ArrayList<String>();
+      testUrls = new ArrayList<>();
       for (String url : args)
       {
         testUrls.add(url);
@@ -603,7 +607,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
                   for (Jws2Instance instance : getDiscoverer().services)
                   {
                     System.out.println("Service " + i++ + " "
-                            + instance.getClass() + "@" + instance.getHost()
+                            + instance.getClass() + "@"
+                            + instance.getHostURL()
                             + ": " + instance.getActionText());
                   }
 
@@ -685,7 +690,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       // return test urls, if there are any, instead of touching cache
       return testUrls;
     }
-    List<String> urls = new ArrayList<String>();
+    List<String> urls = new ArrayList<>();
 
     if (this.preferredUrl != null)
     {
@@ -733,8 +738,8 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
 
   public Vector<Jws2Instance> getServices()
   {
-    return (services == null) ? new Vector<Jws2Instance>()
-            : new Vector<Jws2Instance>(services);
+    return (services == null) ? new Vector<>()
+            : new Vector<>(services);
   }
 
   /**
@@ -839,7 +844,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     if (urlsWithoutServices == null)
     {
-      urlsWithoutServices = new Vector<String>();
+      urlsWithoutServices = new Vector<>();
     }
 
     if ((invalidServiceUrls == null
@@ -859,7 +864,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
   {
     if (invalidServiceUrls == null)
     {
-      invalidServiceUrls = new Vector<String>();
+      invalidServiceUrls = new Vector<>();
     }
     if (!invalidServiceUrls.contains(jwsservers))
     {
@@ -947,14 +952,16 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
    */
   public Jws2Instance getPreferredServiceFor(String[] serviceURLs)
   {
-    HashSet<String> urls = new HashSet<String>();
+    HashSet<String> urls = new HashSet<>();
     urls.addAll(Arrays.asList(serviceURLs));
     Jws2Instance match = null;
     if (services != null)
     {
       for (Jws2Instance svc : services)
       {
-        if (urls.contains(svc.getServiceTypeURI()))
+        // TODO getNameURI Should return a versioned URI for the service, but
+        // doesn't as of 2.11
+        if (urls.contains(svc.getNameURI()))
         {
           if (match == null)
           {
@@ -974,20 +981,21 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     return match;
   }
 
-  Map<String, Map<String, String>> preferredServiceMap = new HashMap<String, Map<String, String>>();;
+  Map<String, Map<String, String>> preferredServiceMap = new HashMap<>();;
 
   /**
-   * get current preferred service of the given type, or global default
+   * get current preferred endpoint of the given Jabaws service, or global
+   * default
    * 
    * @param af
    *          null or a specific alignFrame
-   * @param serviceType
-   *          Jws2Instance.serviceType for service
+   * @param serviceName
+   *          Jws2Instance.getName() for service
    * @return null if no service of this type is available, the preferred service
    *         for the serviceType and af if specified and if defined.
    */
   public Jws2Instance getPreferredServiceFor(AlignFrame af,
-          String serviceType)
+          String serviceName)
   {
     String serviceurl = null;
     synchronized (preferredServiceMap)
@@ -1001,16 +1009,16 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
       }
       if (prefmap != null)
       {
-        serviceurl = prefmap.get(serviceType);
+        serviceurl = prefmap.get(serviceName);
       }
 
     }
     Jws2Instance response = null;
     for (Jws2Instance svc : services)
     {
-      if (svc.serviceType.equals(serviceType))
+      if (svc.getName().equals(serviceName))
       {
-        if (serviceurl == null || serviceurl.equals(svc.getHost()))
+        if (serviceurl == null || serviceurl.equals(svc.getHostURL()))
         {
           response = svc;
           break;
@@ -1020,22 +1028,23 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     return response;
   }
 
-  public void setPreferredServiceFor(AlignFrame af, String serviceType,
+  public void setPreferredServiceFor(AlignFrame af, String serviceName,
           String serviceAction, Jws2Instance selectedServer)
   {
+    // TODO: pull out and generalise for the selectedServer's attributes
     String afid = (af == null) ? "" : af.getViewport().getSequenceSetId();
     if (preferredServiceMap == null)
     {
-      preferredServiceMap = new HashMap<String, Map<String, String>>();
+      preferredServiceMap = new HashMap<>();
     }
     Map<String, String> prefmap = preferredServiceMap.get(afid);
     if (prefmap == null)
     {
-      prefmap = new HashMap<String, String>();
+      prefmap = new HashMap<>();
       preferredServiceMap.put(afid, prefmap);
     }
-    prefmap.put(serviceType, selectedServer.getHost());
-    prefmap.put(serviceAction, selectedServer.getHost());
+    prefmap.put(serviceName, selectedServer.getHostURL());
+    prefmap.put(serviceAction, selectedServer.getHostURL());
   }
 
   public void setPreferredServiceFor(String serviceType,
index 7e68d3b..83d6d16 100644 (file)
@@ -27,7 +27,12 @@ import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
 import jalview.gui.JvSwingUtils;
 import jalview.util.MessageManager;
-import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.WSMenuEntryProviderI;
+import jalview.ws.api.JalviewServiceEndpointProviderI;
+import jalview.ws.api.MultipleSequenceAlignmentI;
+import jalview.ws.api.ServiceWithParameters;
+import jalview.ws.gui.MsaWSThread;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 
 import java.awt.event.ActionEvent;
@@ -40,23 +45,28 @@ import javax.swing.JMenu;
 import javax.swing.JMenuItem;
 import javax.swing.ToolTipManager;
 
-import compbio.data.msa.MsaWS;
-import compbio.metadata.Argument;
-
 /**
- * DOCUMENT ME!
+ * MsaWSClient
+ * 
+ * Instantiates web service menu items for multiple alignment services, and
+ * holds logic for constructing a web service thread.
  * 
- * @author $author$
+ * TODO remove dependency on Jws2Client methods for creating AACon service UI
+ * elements.
+ * 
+ * @author Jim Procter et al
  * @version $Revision$
  */
-public class MsaWSClient extends Jws2Client
+public class MsaWSClient extends Jws2Client implements WSMenuEntryProviderI
 {
   /**
-   * server is a WSDL2Java generated stub for an archetypal MsaWSI service.
+   * server is a proxy class implementing the core methods for submitting,
+   * monitoring and retrieving results from a multiple sequence alignment
+   * service
    */
-  MsaWS server;
+  MultipleSequenceAlignmentI server;
 
-  public MsaWSClient(Jws2Instance sh, String altitle,
+  public MsaWSClient(ServiceWithParameters sh, String altitle,
           jalview.datamodel.AlignmentView msa, boolean submitGaps,
           boolean preserveOrder, AlignmentI seqdataset,
           AlignFrame _alignFrame)
@@ -66,7 +76,8 @@ public class MsaWSClient extends Jws2Client
     // TODO Auto-generated constructor stub
   }
 
-  public MsaWSClient(Jws2Instance sh, WsParamSetI preset, String altitle,
+  public MsaWSClient(ServiceWithParameters sh, WsParamSetI preset,
+          String altitle,
           jalview.datamodel.AlignmentView msa, boolean submitGaps,
           boolean preserveOrder, AlignmentI seqdataset,
           AlignFrame _alignFrame)
@@ -92,8 +103,8 @@ public class MsaWSClient extends Jws2Client
    *          DOCUMENT ME!
    */
 
-  public MsaWSClient(Jws2Instance sh, WsParamSetI preset,
-          List<Argument> arguments, boolean editParams, String altitle,
+  public MsaWSClient(ServiceWithParameters sh, WsParamSetI preset,
+          List<ArgumentI> arguments, boolean editParams, String altitle,
           jalview.datamodel.AlignmentView msa, boolean submitGaps,
           boolean preserveOrder, AlignmentI seqdataset,
           AlignFrame _alignFrame)
@@ -104,25 +115,29 @@ public class MsaWSClient extends Jws2Client
       return;
     }
 
-    if (!(sh.service instanceof MsaWS))
+    if (!(sh instanceof JalviewServiceEndpointProviderI
+            && ((JalviewServiceEndpointProviderI) sh)
+                    .getEndpoint() instanceof MultipleSequenceAlignmentI))
     {
       // redundant at mo - but may change
       JvOptionPane.showMessageDialog(Desktop.desktop,
               MessageManager.formatMessage(
                       "label.service_called_is_not_msa_service",
                       new String[]
-                      { sh.serviceType }),
+                      { sh.getName() }),
               MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
       return;
     }
-    server = (MsaWS) sh.service;
+    serviceHandle = sh;
+    server = (MultipleSequenceAlignmentI) ((JalviewServiceEndpointProviderI) sh)
+            .getEndpoint();
     if ((wsInfo = setWebService(sh, false)) == null)
     {
       JvOptionPane.showMessageDialog(Desktop.desktop, MessageManager
               .formatMessage("label.msa_service_is_unknown", new String[]
-              { sh.serviceType }),
+              { sh.getName() }),
               MessageManager.getString("label.internal_jalview_error"),
               JvOptionPane.WARNING_MESSAGE);
 
@@ -219,16 +234,28 @@ public class MsaWSClient extends Jws2Client
 
   @Override
   public void attachWSMenuEntry(JMenu rmsawsmenu,
-          final Jws2Instance service, final AlignFrame alignFrame)
+          final ServiceWithParameters service, final AlignFrame alignFrame)
   {
-    if (registerAAConWSInstance(rmsawsmenu, service, alignFrame))
+    if (registerAAConWSInstance(rmsawsmenu, service,
+            alignFrame))
     {
       // Alignment dependent analysis calculation WS gui
       return;
     }
+    serviceHandle = service;
     setWebService(service, true); // headless
+    attachWSMenuEntry(rmsawsmenu, alignFrame);
+  }
+
+  @Override
+  public void attachWSMenuEntry(JMenu wsmenu, AlignFrame alignFrame)
+  {
     boolean finished = true, submitGaps = false;
-    JMenu msawsmenu = rmsawsmenu;
+    /**
+     * temp variables holding msa service submenu or root service menu
+     */
+    JMenu msawsmenu = wsmenu;
+    JMenu rmsawsmenu = wsmenu;
     String svcname = WebServiceName;
     if (svcname.endsWith("WS"))
     {
@@ -241,7 +268,8 @@ public class MsaWSClient extends Jws2Client
       rmsawsmenu.add(msawsmenu);
       calcName = "";
     }
-    boolean hasparams = service.hasParameters();
+    boolean hasparams = serviceHandle.hasParameters();
+    ServiceWithParameters service = (ServiceWithParameters) serviceHandle;
     do
     {
       String action = "Align ";
index f9e597f..7d6d341 100644 (file)
@@ -25,6 +25,7 @@ import jalview.datamodel.Annotation;
 import jalview.gui.AlignFrame;
 import jalview.util.MessageManager;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.ArgumentI;
 import jalview.ws.params.WsParamSetI;
 import jalview.ws.uimodel.AlignAnalysisUIText;
 
@@ -40,7 +41,6 @@ import compbio.data.sequence.RNAStructReader.AlifoldResult;
 import compbio.data.sequence.RNAStructScoreManager;
 import compbio.data.sequence.Range;
 import compbio.data.sequence.Score;
-import compbio.metadata.Argument;
 
 /**
  * Client for the JABA RNA Alifold Service
@@ -61,11 +61,11 @@ public class RNAalifoldClient extends JabawsCalcWorker
   boolean bpScores;
 
   public RNAalifoldClient(Jws2Instance sh, AlignFrame alignFrame,
-          WsParamSetI preset, List<Argument> paramset)
+          WsParamSetI preset, List<ArgumentI> paramset)
   {
     super(sh, alignFrame, preset, paramset);
     af = alignFrame;
-    methodName = sh.serviceType;
+    methodName = sh.getName();
     alignedSeqs = true;
     submitGaps = true;
     nucleotidesAllowed = true;
@@ -112,7 +112,7 @@ public class RNAalifoldClient extends JabawsCalcWorker
     if (immediate || !calcMan.isWorking(this) && scoremanager != null)
     {
 
-      List<AlignmentAnnotation> ourAnnot = new ArrayList<AlignmentAnnotation>();
+      List<AlignmentAnnotation> ourAnnot = new ArrayList<>();
 
       // Unpack the ScoreManager
       List<String> structs = ((RNAStructScoreManager) scoremanager)
@@ -231,7 +231,7 @@ public class RNAalifoldClient extends JabawsCalcWorker
 
       // The base pair probabilities are stored in a set in scoreholder. we want
       // a map
-      LinkedHashMap<Range, Float> basePairs = new LinkedHashMap<Range, Float>();
+      LinkedHashMap<Range, Float> basePairs = new LinkedHashMap<>();
       for (Score score : data)
       {
         // The Score objects contain a set of size one containing the range and
@@ -377,7 +377,7 @@ public class RNAalifoldClient extends JabawsCalcWorker
   private LinkedHashMap<Range, Float> isContact(
           LinkedHashMap<Range, Float> basePairs, int i)
   {
-    LinkedHashMap<Range, Float> contacts = new LinkedHashMap<Range, Float>();
+    LinkedHashMap<Range, Float> contacts = new LinkedHashMap<>();
 
     for (Range contact : basePairs.keySet())
     {
index 45bddac..fda9ab5 100644 (file)
@@ -25,6 +25,7 @@ import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.gui.JvSwingUtils;
 import jalview.util.MessageManager;
+import jalview.ws.api.ServiceWithParameters;
 import jalview.ws.jws2.dm.AAConSettings;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.params.WsParamSetI;
@@ -128,7 +129,7 @@ public class SequenceAnnotationWSClient extends Jws2Client
         worker.updateParameters(this.preset, paramset);
       }
     }
-    if (sh.action.toLowerCase().contains("disorder"))
+    if (sh.getAction().toLowerCase().contains("disorder"))
     {
       // build IUPred style client. take sequences, returns annotation per
       // sequence.
@@ -145,7 +146,7 @@ public class SequenceAnnotationWSClient extends Jws2Client
   public SequenceAnnotationWSClient(AAConSettings fave,
           AlignFrame alignFrame, boolean b)
   {
-    super(alignFrame, fave.getPreset(), fave.getJobArgset());
+    super(alignFrame, fave.getPreset(), fave.getArgumentSet());
     initSequenceAnnotationWSClient(fave.getService(), alignFrame,
             fave.getPreset(), b);
   }
@@ -156,7 +157,9 @@ public class SequenceAnnotationWSClient extends Jws2Client
    * @see jalview.ws.jws2.Jws2Client#attachWSMenuEntry(javax.swing.JMenu,
    * jalview.ws.jws2.jabaws2.Jws2Instance, jalview.gui.AlignFrame)
    */
-  public void attachWSMenuEntry(JMenu wsmenu, final Jws2Instance service,
+  @Override
+  public void attachWSMenuEntry(JMenu wsmenu,
+          final ServiceWithParameters service,
           final AlignFrame alignFrame)
   {
     if (registerAAConWSInstance(wsmenu, service, alignFrame))
@@ -166,8 +169,8 @@ public class SequenceAnnotationWSClient extends Jws2Client
     }
     boolean hasparams = service.hasParameters();
     // Assume name ends in WS
-    String calcName = service.serviceType.substring(0,
-            service.serviceType.length() - 2);
+    String calcName = service.getName().substring(0,
+            service.getName().length() - 2);
 
     JMenuItem annotservice = new JMenuItem(MessageManager.formatMessage(
             "label.calcname_with_default_settings", new String[]
@@ -178,7 +181,8 @@ public class SequenceAnnotationWSClient extends Jws2Client
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        new SequenceAnnotationWSClient(service, alignFrame, null, false);
+        new SequenceAnnotationWSClient((Jws2Instance) service, alignFrame,
+                null, false);
       }
     });
     wsmenu.add(annotservice);
@@ -193,9 +197,11 @@ public class SequenceAnnotationWSClient extends Jws2Client
 
       annotservice.addActionListener(new ActionListener()
       {
+        @Override
         public void actionPerformed(ActionEvent e)
         {
-          new SequenceAnnotationWSClient(service, alignFrame, null, true);
+          new SequenceAnnotationWSClient((Jws2Instance) service, alignFrame,
+                  null, true);
         }
       });
       wsmenu.add(annotservice);
@@ -217,9 +223,11 @@ public class SequenceAnnotationWSClient extends Jws2Client
                   + "</strong><br/>" + preset.getDescription()));
           methodR.addActionListener(new ActionListener()
           {
+            @Override
             public void actionPerformed(ActionEvent e)
             {
-              new SequenceAnnotationWSClient(service, alignFrame, preset,
+              new SequenceAnnotationWSClient((Jws2Instance) service,
+                      alignFrame, preset,
                       false);
             }
 
@@ -234,7 +242,7 @@ public class SequenceAnnotationWSClient extends Jws2Client
     {
       annotservice = new JMenuItem(
               MessageManager.getString("label.view_documentation"));
-      if (service.docUrl != null)
+      if (service != null && service.hasDocumentationUrl())
       {
         annotservice.addActionListener(new ActionListener()
         {
@@ -242,13 +250,14 @@ public class SequenceAnnotationWSClient extends Jws2Client
           @Override
           public void actionPerformed(ActionEvent arg0)
           {
-            Desktop.instance.showUrl(service.docUrl);
+            Desktop.instance.showUrl(service.getDocumentationUrl());
           }
         });
         annotservice.setToolTipText(
                 JvSwingUtils.wrapTooltip(true, MessageManager.formatMessage(
                         "label.view_service_doc_url", new String[]
-                        { service.docUrl, service.docUrl })));
+                        { service.getDocumentationUrl(),
+                            service.getDocumentationUrl() })));
         wsmenu.add(annotservice);
       }
     }
index 708787e..5cc8f66 100644 (file)
@@ -76,8 +76,8 @@ public class AAConSettings extends jalview.ws.params.AutoCalcSetting
         preset = pr;
         return;
       }
-      List<ArgumentI> oldargs = new ArrayList<ArgumentI>(),
-              newargs = new ArrayList<ArgumentI>();
+      List<ArgumentI> oldargs = new ArrayList<>(),
+              newargs = new ArrayList<>();
       oldargs.addAll(preset.getArguments());
       // need to compare parameters
       for (ArgumentI newparg : pr.getArguments())
@@ -112,6 +112,7 @@ public class AAConSettings extends jalview.ws.params.AutoCalcSetting
             : JabaParamStore.getJwsArgsfromJaba(jobArgset);
   }
 
+  @Override
   public String getWsParamFile()
   {
     List<Option> opts = null;
@@ -142,7 +143,7 @@ public class AAConSettings extends jalview.ws.params.AutoCalcSetting
   @Override
   public String getServiceURI()
   {
-    return service.getServiceTypeURI();
+    return service.getNameURI();
   }
 
   @Override
index cbfbd3b..f1f5014 100644 (file)
@@ -117,4 +117,10 @@ public class JabaOption implements jalview.ws.params.OptionI
     return opt;
   }
 
+  @Override
+  public List<String> getDisplayNames()
+  {
+    return null; // not supported for Jaba options
+  }
+
 }
diff --git a/src/jalview/ws/jws2/jabaws2/JabawsMsaInstance.java b/src/jalview/ws/jws2/jabaws2/JabawsMsaInstance.java
new file mode 100644 (file)
index 0000000..80de5b2
--- /dev/null
@@ -0,0 +1,285 @@
+package jalview.ws.jws2.jabaws2;
+
+import jalview.bin.Cache;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.gui.WebserviceInfo;
+import jalview.util.MessageManager;
+import jalview.ws.api.CancellableI;
+import jalview.ws.api.JobId;
+import jalview.ws.api.MultipleSequenceAlignmentI;
+import jalview.ws.gui.WsJob;
+import jalview.ws.gui.WsJob.JobState;
+import jalview.ws.jws2.JabaParamStore;
+import jalview.ws.jws2.JabaPreset;
+import jalview.ws.jws2.dm.JabaWsParamSet;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.InvalidArgumentException;
+import jalview.ws.params.WsParamSetI;
+
+import java.io.IOError;
+import java.rmi.ServerError;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import compbio.data.msa.MsaWS;
+import compbio.data.sequence.Alignment;
+import compbio.data.sequence.FastaSequence;
+import compbio.metadata.Argument;
+import compbio.metadata.ChunkHolder;
+import compbio.metadata.JobStatus;
+import compbio.metadata.Preset;
+import compbio.metadata.ResultNotAvailableException;
+
+public class JabawsMsaInstance
+        implements MultipleSequenceAlignmentI, CancellableI
+{
+  /**
+   * our service instance handler generated by the discoverer
+   */
+  Jws2Instance our;
+
+  MsaWS<?> service;
+
+  @Override
+  public JobId align(List<SequenceI> toalign, WsParamSetI parameters,
+          List<ArgumentI> arguments) throws Throwable
+  {
+    List<compbio.data.sequence.FastaSequence> seqs = new ArrayList<>();
+    for (SequenceI seq : toalign)
+    {
+      seqs.add(new FastaSequence(seq.getName(), seq.getSequenceAsString()));
+    }
+    String jobid = null;
+    if (parameters != null)
+    {
+      if (parameters instanceof JabaPreset)
+      {
+        jobid = service.presetAlign(seqs,
+                ((JabaPreset) parameters).getJabaPreset());
+      }
+      else
+      {
+        jobid = service.customAlign(seqs, JabaParamStore
+                .getJabafromJwsArgs(parameters.getArguments()));
+      }
+    }
+    else if (arguments != null && arguments.size() > 0)
+    {
+      jobid = service.customAlign(seqs,
+              JabaParamStore.getJabafromJwsArgs(arguments));
+    }
+    else
+    {
+      jobid = service.align(seqs);
+    }
+
+    if (jobid == null)
+    {
+      return null;
+    }
+    return new JobId(our.getServiceType(), our.getName(), jobid);
+  }
+
+  @Override
+  public AlignmentI getAlignmentFor(JobId jobId)
+          throws InvalidArgumentException, ServerError, IOError
+  {
+    Alignment alignment = null;
+    try
+    {
+      alignment = service.getResult(jobId.getJobId());
+    } catch (ResultNotAvailableException rnotav)
+    {
+
+      // TODO - migrate JABA exception
+      // throw new ServerError("Couldn't get result for job",rnotav);
+    }
+    SequenceI[] alseqs;
+    int alseq_l = 0;
+    if (alignment.getSequences().size() == 0)
+    {
+      return null;
+    }
+
+    alseqs = new SequenceI[alignment.getSequences().size()];
+    for (compbio.data.sequence.FastaSequence seq : alignment.getSequences())
+    {
+      alseqs[alseq_l++] = new Sequence(seq.getId(), seq.getSequence());
+    }
+    AlignmentI jv_al = new jalview.datamodel.Alignment(alseqs);
+    jv_al.setGapCharacter(alignment.getMetadata().getGapchar());
+    return jv_al;
+
+  }
+
+  public JabawsMsaInstance(Jws2Instance handle)
+  {
+    our = handle;
+    service = (MsaWS<?>) our.service;
+  }
+
+  @Override
+  public boolean cancel(WsJob job)
+  {
+    service.cancelJob(job.getJobId());
+    // if the Jaba server indicates the job can't be cancelled, its
+    // because its running on the server's local execution engine
+    // so we just close the window anyway.
+
+    return true;
+  }
+
+  Map<JobStatus, JobState> jwsState = new HashMap<>();
+  {
+    jwsState.put(JobStatus.CANCELLED, JobState.CANCELLED);
+    jwsState.put(JobStatus.COLLECTED, JobState.FINISHED);
+    jwsState.put(JobStatus.FAILED, JobState.FAILED);
+    jwsState.put(JobStatus.FINISHED, JobState.FINISHED);
+    jwsState.put(JobStatus.PENDING, JobState.QUEUED);
+    jwsState.put(JobStatus.RUNNING, JobState.RUNNING);
+    jwsState.put(JobStatus.STARTED, JobState.RUNNING);
+    jwsState.put(JobStatus.SUBMITTED, JobState.SUBMITTED);
+    jwsState.put(JobStatus.UNDEFINED, JobState.UNKNOWN);
+  }
+  @Override
+  public void updateStatus(WsJob job)
+  {
+    JobStatus jwsstatus = service.getJobStatus(job.getJobId());
+    job.setState(jwsState.get(jwsstatus));
+  }
+
+  @Override
+  public boolean updateJobProgress(WsJob job) throws Exception
+  {
+    StringBuilder response = new StringBuilder(job.getStatus());
+    long lastchunk = job.getNextChunk();
+    boolean changed = false;
+    do
+    {
+      ChunkHolder chunk = service.pullExecStatistics(job.getJobId(),
+              lastchunk);
+      if (chunk != null)
+      {
+        changed |= chunk.getChunk().length() > 0;
+        response.append(chunk.getChunk());
+        lastchunk = chunk.getNextPosition();
+        try
+        {
+          Thread.sleep(50);
+        } catch (InterruptedException x)
+        {
+        }
+        ;
+      }
+      ;
+      job.setnextChunk(lastchunk);
+    } while (lastchunk >= 0 && job.getNextChunk() != lastchunk);
+    if (job instanceof WsJob)
+    {
+      // TODO decide if WsJob will be the bean for all ng-webservices
+      job.setStatus(response.toString());
+    }
+    return changed;
+  }
+
+  public boolean isPresetJob(WsJob job)
+  {
+    return job.getPreset() != null && job.getPreset() instanceof JabaPreset;
+  }
+
+  public Preset getServerPreset(WsJob job)
+  {
+    return (isPresetJob(job))
+            ? ((JabaPreset) job.getPreset()).getJabaPreset()
+            : null;
+  }
+
+  public List<Argument> getJabaArguments(WsParamSetI preset)
+  {
+    List<Argument> newargs = new ArrayList<>();
+    if (preset != null)
+    {
+      if (preset instanceof JabaWsParamSet)
+      {
+        newargs.addAll(((JabaWsParamSet) preset).getjabaArguments());
+      }
+      else
+      {
+        newargs.addAll(
+                JabaParamStore.getJabafromJwsArgs(preset.getArguments()));
+      }
+    }
+    return newargs;
+  }
+
+  @Override
+  public boolean handleSubmitError(Throwable _lex, WsJob j,
+          WebserviceInfo wsInfo) throws Exception, Error
+  {
+    if (_lex instanceof compbio.metadata.UnsupportedRuntimeException)
+    {
+      wsInfo.appendProgressText(MessageManager.formatMessage(
+              "info.job_couldnt_be_run_server_doesnt_support_program",
+              new String[]
+              { _lex.getMessage() }));
+      wsInfo.warnUser(_lex.getMessage(),
+              MessageManager.getString("warn.service_not_supported"));
+      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
+      wsInfo.setStatus(j.getJobnum(),
+              WebserviceInfo.STATE_STOPPED_SERVERERROR);
+      return true;
+    }
+    if (_lex instanceof compbio.metadata.LimitExceededException)
+    {
+      wsInfo.appendProgressText(MessageManager.formatMessage(
+              "info.job_couldnt_be_run_exceeded_hard_limit", new String[]
+              { _lex.getMessage() }));
+      wsInfo.warnUser(_lex.getMessage(),
+              MessageManager.getString("warn.input_is_too_big"));
+      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+      wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
+      return true;
+    }
+    if (_lex instanceof compbio.metadata.WrongParameterException)
+    {
+      wsInfo.warnUser(_lex.getMessage(),
+              MessageManager.getString("warn.invalid_job_param_set"));
+      wsInfo.appendProgressText(MessageManager.formatMessage(
+              "info.job_couldnt_be_run_incorrect_param_setting",
+              new String[]
+              { _lex.getMessage() }));
+      wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+      wsInfo.setStatus(j.getJobnum(), WebserviceInfo.STATE_STOPPED_ERROR);
+      return true;
+    }
+    // pass on to generic error handler
+    return false;
+  }
+
+  @Override
+  public boolean handleCollectionException(Exception ex, WsJob msjob,
+          WebserviceInfo wsInfo)
+  {
+    if (ex instanceof compbio.metadata.ResultNotAvailableException)
+    {
+      // job has failed for some reason - probably due to invalid
+      // parameters
+      Cache.log.debug(
+              "Results not available for finished job - marking as broken job.",
+              ex);
+      String status = msjob.getStatus();
+
+      msjob.setStatus(status
+              +
+              "\nResult not available. Probably due to invalid input or parameter settings. Server error message below:\n\n"
+                      + ex.getLocalizedMessage());
+      msjob.setState(WsJob.JobState.BROKEN);
+      return true;
+    }
+    return false;
+  }
+}
index e092192..55799f0 100644 (file)
@@ -23,12 +23,16 @@ package jalview.ws.jws2.jabaws2;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.util.MessageManager;
+import jalview.ws.api.JalviewServiceEndpointProviderI;
+import jalview.ws.api.ServiceWithParameters;
 import jalview.ws.jws2.JabaParamStore;
 import jalview.ws.jws2.MsaWSClient;
 import jalview.ws.jws2.SequenceAnnotationWSClient;
 import jalview.ws.params.ParamDatastoreI;
+import jalview.ws.params.ParamManager;
 
 import java.io.Closeable;
+import java.net.URL;
 
 import javax.swing.JMenu;
 
@@ -38,20 +42,12 @@ import compbio.data.msa.SequenceAnnotation;
 import compbio.metadata.PresetManager;
 import compbio.metadata.RunnerConfig;
 
-public class Jws2Instance implements AutoCloseable
+public class Jws2Instance extends ServiceWithParameters
+        implements JalviewServiceEndpointProviderI, AutoCloseable
 {
-  public String hosturl;
-
-  public String serviceType;
-
-  public String action;
 
   public JABAService service;
 
-  public String description;
-
-  public String docUrl;
-
   /**
    * 
    * @param hosturl
@@ -69,20 +65,31 @@ public class Jws2Instance implements AutoCloseable
   public Jws2Instance(String hosturl, String serviceType, String action,
           String description, JABAService service)
   {
-    super();
-    this.hosturl = hosturl;
-    this.serviceType = serviceType;
+    super(action, action, serviceType, description, hosturl);
     this.service = service;
-    this.action = action;
-    this.description = description;
     int p = description.indexOf("MORE INFORMATION:");
     if (p > -1)
     {
-      docUrl = description.substring(description.indexOf("http", p)).trim();
+      String docUrl = description.substring(description.indexOf("http", p))
+              .trim();
       if (docUrl.indexOf('\n') > -1)
       {
         docUrl = docUrl.substring(0, docUrl.indexOf("\n")).trim();
       }
+      if (docUrl.length() > 0)
+      {
+        try
+        {
+          URL url = new URL(docUrl);
+          if (url != null)
+          {
+            setDocumentationUrl(docUrl);
+          }
+        } catch (Exception x)
+        {
+
+        }
+      }
 
     }
   }
@@ -115,32 +122,12 @@ public class Jws2Instance implements AutoCloseable
       } catch (Exception ex)
       {
         System.err.println("Exception when retrieving presets for service "
-                + serviceType + " at " + hosturl);
+                + getServiceType() + " at " + getHostURL());
       }
     }
     return presets;
   }
 
-  public String getHost()
-  {
-    return hosturl;
-    /*
-     * try { URL serviceurl = new URL(hosturl); if (serviceurl.getPort()!=80) {
-     * return serviceurl.getHost()+":"+serviceurl.getPort(); } return
-     * serviceurl.getHost(); } catch (Exception e) {
-     * System.err.println("Failed to parse service URL '" + hosturl +
-     * "' as a valid URL!"); } return null;
-     */
-  }
-
-  /**
-   * @return short description of what the service will do
-   */
-  public String getActionText()
-  {
-    return action + " with " + serviceType;
-  }
-
   /**
    * non-thread safe - blocks whilst accessing service to get complete set of
    * available options and parameters
@@ -160,7 +147,7 @@ public class Jws2Instance implements AutoCloseable
     throw new Error(MessageManager.formatMessage(
             "error.implementation_error_runner_config_not_available",
             new String[]
-            { serviceType, service.getClass().toString() }));
+            { getServiceType(), service.getClass().toString() }));
   }
 
   @Override
@@ -179,6 +166,7 @@ public class Jws2Instance implements AutoCloseable
     // super.finalize();
   }
 
+  @Override
   public ParamDatastoreI getParamStore()
   {
     if (paramStore == null)
@@ -200,15 +188,19 @@ public class Jws2Instance implements AutoCloseable
 
   public String getUri()
   {
+    // TODO verify that service parameter sets in projects are consistent with
+    // Jalview 2.10.4
     // this is only valid for Jaba 1.0 - this formula might have to change!
-    return hosturl
-            + (hosturl.lastIndexOf("/") == (hosturl.length() - 1) ? ""
+    return getHostURL()
+            + (getHostURL().lastIndexOf("/") == (getHostURL().length() - 1)
+                    ? ""
                     : "/")
-            + serviceType;
+            + getName();
   }
 
   private boolean hasParams = false, lookedForParams = false;
 
+  @Override
   public boolean hasParameters()
   {
     if (!lookedForParams)
@@ -238,9 +230,9 @@ public class Jws2Instance implements AutoCloseable
     }
   }
 
-  public String getServiceTypeURI()
+  public String getNameURI()
   {
-    return "java:" + serviceType;
+    return "java:" + getName();
   }
 
   jalview.ws.uimodel.AlignAnalysisUIText aaui;
@@ -249,4 +241,42 @@ public class Jws2Instance implements AutoCloseable
   {
     return aaui;
   }
+
+  /**
+   * initialise a parameter store for this service
+   * 
+   * @param userParameterStore
+   *          - the user ParamManager (e.g. Desktop.getUserParameterStore() )
+   */
+  @Override
+  public void initParamStore(ParamManager userParameterStore)
+  {
+    if (paramStore == null)
+    {
+      paramStore = new JabaParamStore(this, userParameterStore);
+    }
+  }
+
+  /**
+   * an object that implements one or more interfaces in jalview.ws.api
+   * 
+   * @return
+   */
+  @Override
+  public Object getEndpoint()
+  {
+    if (aaui!=null) {
+      // TODO complete
+      return null;
+    } else {
+      if (service instanceof MsaWS<?>)
+      {
+      return new JabawsMsaInstance(this);
+    } else {
+        // TODO complete
+        // service is for sequence analysis
+        return null;
+    }
+  }
+}
 }
index 2c5386d..af8ae27 100644 (file)
@@ -25,15 +25,49 @@ import java.util.List;
 
 public interface OptionI extends ArgumentI
 {
-
+  /**
+   * Answers a URL with further details for this option, or null if none is
+   * known
+   * 
+   * @return
+   */
   URL getFurtherDetails();
 
+  /**
+   * Answers true if the option is mandatory (a value must be chosen), false if
+   * it is optional
+   * 
+   * @return
+   */
   boolean isRequired();
 
+  /**
+   * Answers the description of the option
+   * 
+   * @return
+   */
   String getDescription();
 
+  /**
+   * Answers a list of possible values that may be chosen for the option (or
+   * null if not applicable)
+   * 
+   * @return
+   */
   List<String> getPossibleValues();
 
-  OptionI copy();
+  /**
+   * Answers a list of display names corresponding to the possible values that
+   * may be chosen for the option (or null if not applicable)
+   * 
+   * @return
+   */
+  List<String> getDisplayNames();
 
+  /**
+   * Answers a new Option with a copy of the settings of this one
+   * 
+   * @return
+   */
+  OptionI copy();
 }
index da46745..d1bdc98 100644 (file)
@@ -29,7 +29,7 @@ public interface ValueConstrainI
 
   public enum ValueType
   {
-    Integer, Float, String
+    Integer, Float, String, Double, File
   };
 
   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);
+  }
+}
diff --git a/src/jalview/ws/params/simple/FileParameter.java b/src/jalview/ws/params/simple/FileParameter.java
new file mode 100644 (file)
index 0000000..aa8e7ad
--- /dev/null
@@ -0,0 +1,47 @@
+package jalview.ws.params.simple;
+
+import jalview.ws.params.ValueConstrainI;
+
+/**
+ * A class that represents a file parameter. User entry options should include
+ * direct input of a file path as text, or file selection using a file browser.
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class FileParameter extends StringParameter
+{
+
+  public FileParameter(String name, String description, boolean required,
+          String defValue, String value)
+  {
+    super(name, description, required, defValue, value);
+  }
+
+  @Override
+  public ValueConstrainI getValidValue()
+  {
+    return new ValueConstrainI()
+    {
+
+      @Override
+      public ValueType getType()
+      {
+        return ValueType.File;
+      }
+
+      @Override
+      public Number getMax()
+      {
+        return null;
+      }
+
+      @Override
+      public Number getMin()
+      {
+        return null;
+      }
+    };
+  }
+
+}
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..ce5d669 100644 (file)
@@ -24,20 +24,125 @@ import jalview.ws.params.OptionI;
 
 import java.net.URL;
 import java.util.ArrayList;
-import java.util.Collection;
 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;
+
+  List<String> possibleVals;
+
+  /*
+   * optional display names corresponding to possibleVals
+   */
+  List<String> displayVals;
 
   boolean required;
 
   URL fdetails;
 
+  /**
+   * Copy constructor
+   * 
+   * @param opt
+   */
+  public Option(Option opt)
+  {
+    name = opt.name;
+    value = opt.value;
+    defvalue = opt.defvalue;
+    description = opt.description;
+    if (opt.possibleVals != null)
+    {
+      possibleVals = new ArrayList<>(opt.possibleVals);
+    }
+    required = opt.required;
+    // URLs are singletons - so we copy by reference. nasty but true.
+    fdetails = opt.fdetails;
+  }
+
+  public Option()
+  {
+  }
+
+  /**
+   * Constructor including display names for possible values
+   * 
+   * @param name2
+   * @param description2
+   * @param isrequired
+   * @param defValue
+   * @param val
+   * @param possibleVals
+   * @param fdetails
+   */
+  public Option(String name2, String description2, boolean isrequired,
+          String defValue, String val, List<String> possibleVals,
+          List<String> displayNames, URL fdetails)
+  {
+    name = name2;
+    description = description2;
+    this.value = val;
+    this.required = isrequired;
+    this.defvalue = defValue;
+    if (possibleVals != null)
+    {
+      this.possibleVals = new ArrayList<>(possibleVals);
+    }
+    if (displayNames != null)
+    {
+      this.displayVals = new ArrayList<>(displayNames);
+    }
+    this.fdetails = fdetails;
+  }
+
+  /**
+   * Constructor
+   * 
+   * @param name2
+   * @param description2
+   * @param isrequired
+   * @param defValue
+   * @param val
+   * @param possibleVals
+   * @param fdetails
+   */
+  public Option(String name2, String description2, boolean isrequired,
+          String defValue, String val, List<String> possibleVals,
+          URL fdetails)
+  {
+    this(name2, description2, isrequired, defValue, val, possibleVals, null,
+            fdetails);
+  }
+
+  @Override
+  public OptionI copy()
+  {
+    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;
+  }
+
   @Override
   public String getName()
   {
@@ -80,49 +185,9 @@ public class Option implements OptionI
     return possibleVals;
   }
 
-  public Option(Option opt)
-  {
-    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();
-    }
-    required = opt.required;
-    // URLs are singletons - so we copy by reference. nasty but true.
-    fdetails = opt.fdetails;
-  }
-
-  public Option()
-  {
-  }
-
-  public Option(String name2, String description2, boolean isrequired,
-          String defValue, String value, Collection<String> possibleVals,
-          URL fdetails)
-  {
-    name = name2;
-    description = description2;
-    this.value = value;
-    this.required = isrequired;
-    this.defvalue = defValue;
-    if (possibleVals != null)
-    {
-      this.possibleVals = new ArrayList<String>();
-      this.possibleVals.addAll(possibleVals);
-    }
-    this.fdetails = fdetails;
-  }
-
   @Override
-  public OptionI copy()
+  public List<String> getDisplayNames()
   {
-    Option opt = new Option(this);
-    return opt;
+    return displayVals;
   }
 }
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();
-}
  */
 package jalview.ws.params.simple;
 
-public class StringChoiceParameter extends Option
+import java.util.List;
+
+/**
+ * A parameter with a choice of possible options, preferred to be rendered as
+ * radio buttons if possible
+ */
+public class RadioChoiceParameter extends StringParameter
 {
 
+  /**
+   * Constructor
+   * 
+   * @param name
+   * @param description
+   * @param options
+   * @param def
+   */
+  public RadioChoiceParameter(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..d3d899c
--- /dev/null
@@ -0,0 +1,88 @@
+package jalview.ws.params.simple;
+
+import jalview.ws.params.ParameterI;
+import jalview.ws.params.ValueConstrainI;
+
+import java.util.List;
+
+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;
+    this.possibleVals = parm.possibleVals;
+    this.displayVals = parm.displayVals;
+  }
+
+  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 and (optionally)
+   * corresponding display names
+   * 
+   * @param name2
+   * @param description2
+   * @param isrequired
+   * @param defValue
+   * @param value
+   * @param possibleVals
+   * @param displayNames
+   */
+  public StringParameter(String name2, String description2,
+          boolean isrequired, String defValue, String value,
+          List<String> possibleVals, List<String> displayNames)
+  {
+    super(name2, description2, isrequired, defValue, value, possibleVals,
+            displayNames, null);
+  }
+}
index 88431a6..c83879a 100644 (file)
@@ -30,7 +30,6 @@ import jalview.ws.params.simple.Option;
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -58,9 +57,9 @@ public abstract class InputType
   {
     NUC, PROT, MIX;
 
-    public static Collection<String> toStringValues()
+    public static List<String> toStringValues()
     {
-      Collection<String> c = new ArrayList<String>();
+      List<String> c = new ArrayList<>();
       for (molType type : values())
       {
         c.add(type.toString());
@@ -75,7 +74,7 @@ public abstract class InputType
 
   public int max = 0; // unbounded
 
-  protected ArrayList<Class> inputData = new ArrayList<Class>();
+  protected List<Class> inputData = new ArrayList<>();
 
   /**
    * initialise the InputType with a list of jalview data classes that the
@@ -104,7 +103,9 @@ public abstract class InputType
   public boolean validFor(RestJob restJob)
   {
     if (!validFor(restJob.rsd))
+    {
       return false;
+    }
     for (Class cl : inputData)
     {
       if (!restJob.hasDataOfType(cl))
@@ -118,7 +119,9 @@ public abstract class InputType
   public boolean validFor(RestServiceDescription restServiceDescription)
   {
     if (!restServiceDescription.inputParams.values().contains(this))
+    {
       return false;
+    }
 
     return true;
   }
@@ -270,7 +273,7 @@ public abstract class InputType
 
   public List<OptionI> getBaseOptions()
   {
-    ArrayList<OptionI> opts = new ArrayList<OptionI>();
+    ArrayList<OptionI> opts = new ArrayList<>();
     opts.add(new IntegerParameter("min",
             "Minimum number of data of this type", true, 1, min, 0, -1));
     opts.add(new IntegerParameter("max",
@@ -295,7 +298,7 @@ public abstract class InputType
   public void configureFromArgumentI(List<ArgumentI> currentSettings)
           throws InvalidArgumentException
   {
-    ArrayList<String> urltoks = new ArrayList<String>();
+    List<String> urltoks = new ArrayList<>();
     String rg;
     for (ArgumentI arg : currentSettings)
     {
index a71b70d..d84206f 100644 (file)
@@ -28,15 +28,14 @@ import jalview.gui.AlignmentPanel;
 import jalview.gui.Desktop;
 import jalview.gui.JvOptionPane;
 import jalview.gui.WebserviceInfo;
-import jalview.io.packed.DataProvider.JvDataType;
 import jalview.util.MessageManager;
 import jalview.ws.WSClient;
 import jalview.ws.WSClientI;
 import jalview.ws.WSMenuEntryProviderI;
+import jalview.ws.rest.clientdefs.ShmrRestClient;
 
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.util.Hashtable;
 import java.util.Vector;
 
 import javax.swing.JMenu;
@@ -99,12 +98,12 @@ public class RestClient extends WSClient
   {
     WebServiceJobTitle = MessageManager
             .formatMessage("label.webservice_job_title", new String[]
-            { service.details.Action, service.details.Name });
-    WebServiceName = service.details.Name;
+            { service.details.getAction(), service.details.getName() });
+    WebServiceName = service.details.getName();
     WebServiceReference = "No reference - go to url for more info";
-    if (service.details.description != null)
+    if (service.details.getDescription() != null)
     {
-      WebServiceReference = service.details.description;
+      WebServiceReference = service.details.getDescription();
     }
     if (!headless)
     {
@@ -141,10 +140,10 @@ public class RestClient extends WSClient
   public void attachWSMenuEntry(final JMenu wsmenu,
           final AlignFrame alignFrame)
   {
-    JMenuItem submit = new JMenuItem(service.details.Name);
+    JMenuItem submit = new JMenuItem(service.details.getName());
     submit.setToolTipText(MessageManager
             .formatMessage("label.rest_client_submit", new String[]
-            { service.details.Action, service.details.Name }));
+            { service.details.getAction(), service.details.getName() }));
     submit.addActionListener(new ActionListener()
     {
 
@@ -339,46 +338,6 @@ public class RestClient extends WSClient
     }
   }
 
-  public static RestClient makeShmmrRestClient()
-  {
-    String action = "Analysis",
-            description = "Sequence Harmony and Multi-Relief (Brandt et al. 2010)",
-            name = MessageManager.getString("label.multiharmony");
-    Hashtable<String, InputType> iparams = new Hashtable<String, InputType>();
-    jalview.ws.rest.params.JobConstant toolp;
-    // toolp = new jalview.ws.rest.JobConstant("tool","jalview");
-    // iparams.put(toolp.token, toolp);
-    // toolp = new jalview.ws.rest.params.JobConstant("mbjob[method]","shmr");
-    // iparams.put(toolp.token, toolp);
-    // toolp = new
-    // jalview.ws.rest.params.JobConstant("mbjob[description]","step 1");
-    // iparams.put(toolp.token, toolp);
-    // toolp = new jalview.ws.rest.params.JobConstant("start_search","1");
-    // iparams.put(toolp.token, toolp);
-    // toolp = new jalview.ws.rest.params.JobConstant("blast","0");
-    // iparams.put(toolp.token, toolp);
-
-    jalview.ws.rest.params.Alignment aliinput = new jalview.ws.rest.params.Alignment();
-    // SHMR server has a 65K limit for content pasted into the 'ali' parameter,
-    // so we always upload our files.
-    aliinput.token = "ali_file";
-    aliinput.writeAsFile = true;
-    iparams.put(aliinput.token, aliinput);
-    jalview.ws.rest.params.SeqGroupIndexVector sgroups = new jalview.ws.rest.params.SeqGroupIndexVector();
-    sgroups.setMinsize(2);
-    sgroups.min = 2;// need at least two group defined to make a partition
-    iparams.put("groups", sgroups);
-    sgroups.token = "groups";
-    sgroups.sep = " ";
-    RestServiceDescription shmrService = new RestServiceDescription(action,
-            description, name,
-            "http://zeus.few.vu.nl/programs/shmrwww/index.php?tool=jalview", // ?tool=jalview&mbjob[method]=shmr&mbjob[description]=step1",
-            "?tool=jalview", iparams, true, false, '-');
-    // a priori knowledge of the data returned from the service
-    shmrService.addResultDatatype(JvDataType.ANNOTATION);
-    return new RestClient(shmrService);
-  }
-
   public AlignmentPanel recoverAlignPanelForView()
   {
     AlignmentPanel[] aps = Desktop
@@ -407,13 +366,13 @@ public class RestClient extends WSClient
   {
     if (services == null)
     {
-      services = new Vector<String>();
+      services = new Vector<>();
       try
       {
         for (RestServiceDescription descr : RestServiceDescription
-                .parseDescriptions(
-                        jalview.bin.Cache.getDefault(RSBS_SERVICES,
-                                makeShmmrRestClient().service.toString())))
+                .parseDescriptions(jalview.bin.Cache.getDefault(
+                        RSBS_SERVICES,
+                        ShmrRestClient.makeShmmrRestClient().service.toString())))
         {
           services.add(descr.toString());
         }
@@ -436,7 +395,7 @@ public class RestClient extends WSClient
 
   public String getAction()
   {
-    return service.details.Action;
+    return service.details.getAction();
   }
 
   public RestServiceDescription getRestDescription()
@@ -446,7 +405,7 @@ public class RestClient extends WSClient
 
   public static Vector<String> getRsbsDescriptions()
   {
-    Vector<String> rsbsDescrs = new Vector<String>();
+    Vector<String> rsbsDescrs = new Vector<>();
     for (RestClient rsbs : getRestClients())
     {
       rsbsDescrs.add(rsbs.getRestDescription().toString());
@@ -459,7 +418,7 @@ public class RestClient extends WSClient
     if (rsbsUrls != null)
     {
       // TODO: consider validating services ?
-      services = new Vector<String>(rsbsUrls);
+      services = new Vector<>(rsbsUrls);
       StringBuffer sprop = new StringBuffer();
       for (String s : services)
       {
index acb7904..f60ff0c 100644 (file)
@@ -59,8 +59,6 @@ import org.apache.http.client.methods.HttpRequestBase;
 import org.apache.http.entity.mime.HttpMultipartMode;
 import org.apache.http.entity.mime.MultipartEntity;
 import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.HttpContext;
 import org.apache.http.util.EntityUtils;
 
 public class RestJobThread extends AWSThread
@@ -216,9 +214,6 @@ public class RestJobThread extends AWSThread
   protected void doHttpReq(Stage stg, RestJob rj, String postUrl)
           throws Exception
   {
-    StringBuffer respText = new StringBuffer();
-    // con.setContentHandlerFactory(new
-    // jalview.ws.io.mime.HttpContentHandler());
     HttpRequestBase request = null;
     String messages = "";
     if (stg == Stage.SUBMIT)
@@ -253,7 +248,6 @@ public class RestJobThread extends AWSThread
     {
       DefaultHttpClient httpclient = new DefaultHttpClient();
 
-      HttpContext localContext = new BasicHttpContext();
       HttpResponse response = null;
       try
       {
@@ -287,39 +281,21 @@ public class RestJobThread extends AWSThread
         Cache.log.debug("Processing result set.");
         processResultSet(rj, response, request);
         break;
+
       case 202:
-        rj.statMessage = "<br>Job submitted successfully. Results available at this URL:\n"
-                + "<a href=" + rj.getJobId() + "\">" + rj.getJobId()
-                + "</a><br>";
-        rj.running = true;
+        markJobAsRunning(rj);
         break;
+
+      case 201:
+        // Created - redirect may be present. Fallthrough to 302
       case 302:
-        Header[] loc;
-        if (!rj.isSubmitted()
-                && (loc = response
-                        .getHeaders(HTTPConstants.HEADER_LOCATION)) != null
-                && loc.length > 0)
-        {
-          if (loc.length > 1)
-          {
-            Cache.log.warn("Ignoring additional " + (loc.length - 1)
-                    + " location(s) provided in response header ( next one is '"
-                    + loc[1].getValue() + "' )");
-          }
-          rj.setJobId(loc[0].getValue());
-          rj.setSubmitted(true);
-        }
+        extractJobId(rj, response);
         completeStatus(rj, response);
         break;
       case 500:
-        // Failed.
-        rj.setSubmitted(true);
-        rj.setAllowedServerExceptions(0);
-        rj.setSubjobComplete(true);
-        rj.error = true;
-        rj.running = false;
-        completeStatus(rj, response,
-                "" + getStage(stg) + "failed. Reason below:\n");
+        markAsFailed(rj, response);
+        completeStatus(rj, response, "" + getStage(stg)
+                + "failed. Reason below:\n");
         break;
       default:
         // Some other response. Probably need to pop up the content in a window.
@@ -346,6 +322,64 @@ public class RestJobThread extends AWSThread
     }
   }
 
+  private void markAsFailed(RestJob rj, HttpResponse response)
+  {
+    // Failed.
+    rj.setSubmitted(true);
+    rj.setAllowedServerExceptions(0);
+    rj.setSubjobComplete(true);
+    rj.error = true;
+    rj.running = false;
+  }
+
+  /**
+   * set the jobRunning flag and post a link to the physical result page encoded
+   * in rj.getJobId()
+   * 
+   * @param rj
+   */
+  private void markJobAsRunning(RestJob rj)
+  {
+    rj.statMessage = "<br>Job submitted successfully. Results available at this URL:\n"
+            + "<a href="
+            + rj.getJobId()
+            + "\">"
+            + rj.getJobId()
+            + "</a><br>";
+    rj.running = true;
+  }
+
+  /**
+   * extract the job ID URL from the redirect page. Does nothing if job is
+   * already running.
+   * 
+   * @param rj
+   * @param response
+   */
+  private void extractJobId(RestJob rj, HttpResponse response)
+  {
+    Header[] loc;
+    if (!rj.isSubmitted())
+    {
+
+      // redirect URL - typical for IBIVU type jobs.
+      if ((loc = response.getHeaders(HTTPConstants.HEADER_LOCATION)) != null
+              && loc.length > 0)
+      {
+        if (loc.length > 1)
+        {
+          Cache.log
+                  .warn("Ignoring additional "
+                          + (loc.length - 1)
+                          + " location(s) provided in response header ( next one is '"
+                          + loc[1].getValue() + "' )");
+        }
+        rj.setJobId(loc[0].getValue());
+        rj.setSubmitted(true);
+      }
+    }
+  }
+
   /**
    * job has completed. Something valid should be available from con
    * 
@@ -575,12 +609,12 @@ public class RestJobThread extends AWSThread
     /**
      * alignment panels derived from each alignment set returned by service.
      */
-    ArrayList<jalview.gui.AlignmentPanel> destPanels = new ArrayList<jalview.gui.AlignmentPanel>();
+    ArrayList<jalview.gui.AlignmentPanel> destPanels = new ArrayList<>();
     /**
      * list of instructions for how to process each distinct alignment set
      * returned by the job set
      */
-    ArrayList<AddDataTo> resultDest = new ArrayList<AddDataTo>();
+    ArrayList<AddDataTo> resultDest = new ArrayList<>();
     /**
      * when false, zeroth pane is panel derived from input deta.
      */
@@ -599,9 +633,9 @@ public class RestJobThread extends AWSThread
     boolean vsepjobs = restClient.service.isVseparable();
     // total number of distinct alignment sets generated by job set.
     int numAlSets = 0, als = 0;
-    List<AlignmentI> destAls = new ArrayList<AlignmentI>();
-    List<jalview.datamodel.HiddenColumns> destColsel = new ArrayList<jalview.datamodel.HiddenColumns>();
-    List<List<NewickFile>> trees = new ArrayList<List<NewickFile>>();
+    List<AlignmentI> destAls = new ArrayList<>();
+    List<jalview.datamodel.HiddenColumns> destColsel = new ArrayList<>();
+    List<List<NewickFile>> trees = new ArrayList<>();
 
     do
     {
@@ -660,7 +694,7 @@ public class RestJobThread extends AWSThread
 
               if (alset.trees != null)
               {
-                trees.add(new ArrayList<NewickFile>(alset.trees));
+                trees.add(new ArrayList<>(alset.trees));
               }
               else
               {
@@ -688,8 +722,8 @@ public class RestJobThread extends AWSThread
        */
       int vrestjob = 0;
       // Destination alignments for all result data.
-      ArrayList<SequenceGroup> visgrps = new ArrayList<SequenceGroup>();
-      Hashtable<String, SequenceGroup> groupNames = new Hashtable<String, SequenceGroup>();
+      ArrayList<SequenceGroup> visgrps = new ArrayList<>();
+      Hashtable<String, SequenceGroup> groupNames = new Hashtable<>();
       ArrayList<AlignmentAnnotation> visAlAn = null;
       for (nvertsep = 0; nvertsep < nvertseps; nvertsep++)
       {
@@ -953,7 +987,7 @@ public class RestJobThread extends AWSThread
                 }
                 if (visAlAn == null)
                 {
-                  visAlAn = new ArrayList<AlignmentAnnotation>();
+                  visAlAn = new ArrayList<>();
                 }
                 AlignmentAnnotation visan = null;
                 for (AlignmentAnnotation v : visAlAn)
@@ -1037,8 +1071,9 @@ public class RestJobThread extends AWSThread
       HiddenColumns destcs;
       String alTitle = MessageManager
               .formatMessage("label.webservice_job_title_on", new String[]
-              { restClient.service.details.Action,
-                  restClient.service.details.Name, restClient.viewTitle });
+              { restClient.service.details.getAction(),
+                  restClient.service.details.getName(),
+                  restClient.viewTitle });
       switch (action)
       {
       case newAlignment:
@@ -1248,7 +1283,7 @@ public class RestJobThread extends AWSThread
    */
   public boolean isValid()
   {
-    ArrayList<String> _warnings = new ArrayList<String>();
+    ArrayList<String> _warnings = new ArrayList<>();
     boolean validt = true;
     if (jobs != null)
     {
index 5533406..b07f3b6 100644 (file)
@@ -23,6 +23,7 @@ package jalview.ws.rest;
 import jalview.datamodel.SequenceI;
 import jalview.io.packed.DataProvider.JvDataType;
 import jalview.util.StringUtils;
+import jalview.ws.api.UIinfo;
 import jalview.ws.rest.params.Alignment;
 import jalview.ws.rest.params.AnnotationFile;
 import jalview.ws.rest.params.SeqGroupIndexVector;
@@ -66,10 +67,7 @@ public class RestServiceDescription
           boolean vseparable, char gapCharacter)
   {
     super();
-    this.details = new UIinfo();
-    details.Action = action == null ? "" : action;
-    details.description = description == null ? "" : description;
-    details.Name = name == null ? "" : name;
+    this.details = new UIinfo(action, action, name, description, postUrl);
     this.postUrl = postUrl == null ? "" : postUrl;
     this.urlSuffix = urlSuffix == null ? "" : urlSuffix;
     if (inputParams != null)
@@ -98,56 +96,11 @@ public class RestServiceDescription
     // TODO - robust diff that includes constants and reordering of URL
     // diff |= !(postUrl.equals(other.postUrl));
     // diff |= !inputParams.equals(other.inputParams);
-    diff |= !details.Name.equals(other.details.Name);
-    diff |= !details.Action.equals(other.details.Action);
-    diff |= !details.description.equals(other.details.description);
+    diff |= !details.equals(other.details);
     return !diff;
   }
 
-  /**
-   * Service UI Info { Action, Specific Name of Service, Brief Description }
-   */
-
-  public class UIinfo
-  {
-    public String getAction()
-    {
-      return Action;
-    }
-
-    public void setAction(String action)
-    {
-      Action = action;
-    }
-
-    public String getName()
-    {
-      return Name;
-    }
-
-    public void setName(String name)
-    {
-      Name = name;
-    }
-
-    public String getDescription()
-    {
-      return description;
-    }
-
-    public void setDescription(String description)
-    {
-      this.description = description;
-    }
-
-    String Action;
-
-    String Name;
-
-    String description;
-  }
-
-  public UIinfo details = new UIinfo();
+  public UIinfo details;
 
   public String getAction()
   {
@@ -238,7 +191,7 @@ public class RestServiceDescription
   /**
    * input info given as key/value pairs - mapped to post arguments
    */
-  Map<String, InputType> inputParams = new HashMap<String, InputType>();
+  Map<String, InputType> inputParams = new HashMap<>();
 
   /**
    * assigns the given inputType it to its corresponding input parameter token
@@ -455,7 +408,7 @@ public class RestServiceDescription
     }
     StringTokenizer st = new StringTokenizer(outstring, ";");
     String tok = "";
-    resultData = new ArrayList<JvDataType>();
+    resultData = new ArrayList<>();
     while (st.hasMoreTokens())
     {
       try
@@ -479,7 +432,7 @@ public class RestServiceDescription
 
   private String getServiceIOProperties()
   {
-    ArrayList<String> vls = new ArrayList<String>();
+    ArrayList<String> vls = new ArrayList<>();
     if (isHseparable())
     {
       vls.add("hseparable");
@@ -496,17 +449,18 @@ public class RestServiceDescription
             ",");
   }
 
+  @Override
   public String toString()
   {
     StringBuffer result = new StringBuffer();
     result.append("|");
-    result.append(details.Name);
+    result.append(details.getName());
     result.append('|');
-    result.append(details.Action);
+    result.append(details.getAction());
     result.append('|');
-    if (details.description != null)
+    if (details.getDescription() != null)
     {
-      result.append(details.description);
+      result.append(details.getDescription());
     }
     ;
     // list job input flags
@@ -567,9 +521,8 @@ public class RestServiceDescription
     {
       p++;
     }
-    details.Name = list[p];
-    details.Action = list[p + 1];
-    details.description = list[p + 2];
+    String action = list[p + 1], name = list[p], descrip = list[p + 2];
+
     invalid |= !configureFromServiceInputProperties(list[p + 3], warnings);
     if (list.length - p > 5 && list[p + 5] != null
             && list[p + 5].trim().length() > 5)
@@ -589,6 +542,7 @@ public class RestServiceDescription
         p += 5;
       }
     }
+    details = new UIinfo(action, action, name, descrip, postUrl);
     return invalid ? -1 : p;
   }
 
@@ -667,7 +621,7 @@ public class RestServiceDescription
     int lastp = 0;
     String url = new String();
     Matcher prms = PARAM_ENCODED_URL_PATTERN.matcher(ipurl);
-    Map<String, InputType> iparams = new Hashtable<String, InputType>();
+    Map<String, InputType> iparams = new Hashtable<>();
     InputType jinput;
     while (prms.find())
     {
@@ -728,7 +682,7 @@ public class RestServiceDescription
         jinput = (InputType) (type.getConstructor().newInstance());
         if (iprm.equalsIgnoreCase(jinput.getURLtokenPrefix()))
         {
-          ArrayList<String> al = new ArrayList<String>();
+          ArrayList<String> al = new ArrayList<>();
           for (String prprm : StringUtils.separatorListToArray(iprmparams,
                   ","))
           {
@@ -838,7 +792,7 @@ public class RestServiceDescription
     return jobId + urlSuffix;
   }
 
-  private List<JvDataType> resultData = new ArrayList<JvDataType>();
+  private List<JvDataType> resultData = new ArrayList<>();
 
   /**
    * 
@@ -852,7 +806,7 @@ public class RestServiceDescription
   {
     if (resultData == null)
     {
-      resultData = new ArrayList<JvDataType>();
+      resultData = new ArrayList<>();
     }
     resultData.add(dt);
   }
@@ -883,7 +837,7 @@ public class RestServiceDescription
           String services) throws Exception
   {
     String[] list = StringUtils.separatorListToArray(services, "|");
-    List<RestServiceDescription> svcparsed = new ArrayList<RestServiceDescription>();
+    List<RestServiceDescription> svcparsed = new ArrayList<>();
     int p = 0, lastp = 0;
     StringBuffer warnings = new StringBuffer();
     do
diff --git a/src/jalview/ws/rest/clientdefs/ShmrRestClient.java b/src/jalview/ws/rest/clientdefs/ShmrRestClient.java
new file mode 100644 (file)
index 0000000..a10931b
--- /dev/null
@@ -0,0 +1,58 @@
+package jalview.ws.rest.clientdefs;
+
+import jalview.io.packed.DataProvider.JvDataType;
+import jalview.util.MessageManager;
+import jalview.ws.rest.InputType;
+import jalview.ws.rest.RestClient;
+import jalview.ws.rest.RestServiceDescription;
+import jalview.ws.rest.params.Alignment;
+import jalview.ws.rest.params.JobConstant;
+import jalview.ws.rest.params.SeqGroupIndexVector;
+
+import java.util.Hashtable;
+
+public class ShmrRestClient
+{
+
+  public static RestClient makeShmmrRestClient()
+  {
+    String action = "Analysis", description = "Sequence Harmony and Multi-Relief (Brandt et al. 2010)", name = MessageManager
+            .getString("label.multiharmony");
+    Hashtable<String, InputType> iparams = new Hashtable<String, InputType>();
+    jalview.ws.rest.params.JobConstant toolp;
+    // toolp = new jalview.ws.rest.JobConstant("tool","jalview");
+    // iparams.put(toolp.token, toolp);
+    // toolp = new jalview.ws.rest.params.JobConstant("mbjob[method]","shmr");
+    // iparams.put(toolp.token, toolp);
+    // toolp = new
+    // jalview.ws.rest.params.JobConstant("mbjob[description]","step 1");
+    // iparams.put(toolp.token, toolp);
+    // toolp = new jalview.ws.rest.params.JobConstant("start_search","1");
+    // iparams.put(toolp.token, toolp);
+    // toolp = new jalview.ws.rest.params.JobConstant("blast","0");
+    // iparams.put(toolp.token, toolp);
+  
+    jalview.ws.rest.params.Alignment aliinput = new jalview.ws.rest.params.Alignment();
+    // SHMR server has a 65K limit for content pasted into the 'ali' parameter,
+    // so we always upload our files.
+    aliinput.token = "ali_file";
+    aliinput.writeAsFile = true;
+    iparams.put(aliinput.token, aliinput);
+    jalview.ws.rest.params.SeqGroupIndexVector sgroups = new jalview.ws.rest.params.SeqGroupIndexVector();
+    sgroups.setMinsize(2);
+    sgroups.min = 2;// need at least two group defined to make a partition
+    iparams.put("groups", sgroups);
+    sgroups.token = "groups";
+    sgroups.sep = " ";
+    RestServiceDescription shmrService = new RestServiceDescription(
+            action,
+            description,
+            name,
+            "http://zeus.few.vu.nl/programs/shmrwww/index.php?tool=jalview",// ?tool=jalview&mbjob[method]=shmr&mbjob[description]=step1",
+            "?tool=jalview", iparams, true, false, '-');
+    // a priori knowledge of the data returned from the service
+    shmrService.addResultDatatype(JvDataType.ANNOTATION);
+    return new RestClient(shmrService);
+  }
+
+}
index cb90984..3a1520a 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 35f78f3..ac5e9a1 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 6f5ef65..7875ac8 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 6780323..4b3ef32 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 5edb2e8..8544216 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 68ebf9b..26f98a0 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 39fc0c3..b737c9a 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index c92f72c..af7764f 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 0c21215..328e432 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 36b454f..33722cd 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 0ea2491..e1a7b05 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
@@ -96,6 +96,7 @@ import javax.xml.datatype.XMLGregorianCalendar;
  *                         &lt;/complexContent>
  *                       &lt;/complexType>
  *                     &lt;/element>
+ *                     &lt;element name="hmmerProfile" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
  *                   &lt;/sequence>
  *                   &lt;attribute name="colour" type="{http://www.w3.org/2001/XMLSchema}int" />
  *                   &lt;attribute name="start" use="required" type="{http://www.w3.org/2001/XMLSchema}int" />
@@ -1945,6 +1946,7 @@ public class JalviewModel {
      *             &lt;/complexContent>
      *           &lt;/complexType>
      *         &lt;/element>
+     *         &lt;element name="hmmerProfile" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
      *       &lt;/sequence>
      *       &lt;attribute name="colour" type="{http://www.w3.org/2001/XMLSchema}int" />
      *       &lt;attribute name="start" use="required" type="{http://www.w3.org/2001/XMLSchema}int" />
@@ -1964,7 +1966,8 @@ public class JalviewModel {
         "features",
         "pdbids",
         "hiddenSequences",
-        "rnaViewer"
+        "rnaViewer",
+        "hmmerProfile"
     })
     public static class JSeq {
 
@@ -1976,6 +1979,8 @@ public class JalviewModel {
         protected List<Integer> hiddenSequences;
         @XmlElement(namespace = "www.jalview.org")
         protected List<JalviewModel.JSeq.RnaViewer> rnaViewer;
+        @XmlElement(namespace = "www.jalview.org")
+        protected String hmmerProfile;
         @XmlAttribute(name = "colour")
         protected Integer colour;
         @XmlAttribute(name = "start", required = true)
@@ -2106,6 +2111,30 @@ public class JalviewModel {
         }
 
         /**
+         * Gets the value of the hmmerProfile property.
+         * 
+         * @return
+         *     possible object is
+         *     {@link String }
+         *     
+         */
+        public String getHmmerProfile() {
+            return hmmerProfile;
+        }
+
+        /**
+         * Sets the value of the hmmerProfile property.
+         * 
+         * @param value
+         *     allowed object is
+         *     {@link String }
+         *     
+         */
+        public void setHmmerProfile(String value) {
+            this.hmmerProfile = value;
+        }
+
+        /**
          * Gets the value of the colour property.
          * 
          * @return
index c43e04c..8fea467 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 1a31d82..ef08f78 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 5ebeb7e..be17af9 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 9db4ea3..5bb3d66 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index e0b2127..55ca7cd 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 6234f32..dca3b94 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index d5132ab..b5005fa 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index b842947..8b53f2e 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 6aee6ac..025c91f 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index aef7543..2b94a3d 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 1b3d6d4..3e64568 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 5d341c3..1f1c2a0 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 659eab9..3cab774 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 
index 3ed532d..fd74613 100644 (file)
@@ -2,7 +2,7 @@
 // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.8-b130911.1802 
 // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
 // Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2019.06.07 at 02:21:15 PM BST 
+// Generated on: 2019.07.10 at 12:10:00 PM BST 
 //
 
 @javax.xml.bind.annotation.XmlSchema(namespace = "www.vamsas.ac.uk/jalview/version2", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
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 dd19eb6..fa73aba 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..65241b4
--- /dev/null
@@ -0,0 +1,162 @@
+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;
+
+  HiddenMarkovModel alignmentHmm;
+
+  @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();
+
+    // used to check if consensus sequence is automatically aligned with alignment
+    HMMFile alignmentTest = new HMMFile(
+            new FileParse("test/jalview/io/HMMAlignmentTestHMM.hmm",
+                    DataSourceType.FILE));
+    alignmentHmm = alignmentTest.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------");
+
+    // test to see if consensus sequence maps to alignment correctly
+    // see HMMAlignmentTest.sto for corresponding alignment file
+    SequenceI seq2 = alignmentHmm.getConsensusSequence();
+    assertEquals(seq2.getCharAt(0), '-');
+    assertEquals(seq2.getCharAt(7), '-');
+    assertEquals(seq2.getCharAt(8), 's');
+
+  }
+
+  /**
+   * 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 8419d4c..e0f4eba 100644 (file)
@@ -244,7 +244,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);
@@ -309,7 +309,7 @@ public class SequenceGroupTest
   {
     SequenceI s1 = new Sequence("abcde", "fg");
     SequenceI s2 = new Sequence("foo", "bar");
-    List<SequenceI> seqs = new ArrayList<SequenceI>();
+    List<SequenceI> seqs = new ArrayList<>();
     seqs.add(s1);
     seqs.add(s2);
     SequenceGroup sg = new SequenceGroup(seqs);
index d2284f1..1a4920d 100644 (file)
@@ -27,6 +27,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;
@@ -48,6 +49,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;
@@ -210,7 +212,7 @@ public class AlignFrameTest
   @Test(groups = "Functional")
   public void testChangeColour_background_groupsAndThresholds()
   {
-    AlignViewport av = af.getViewport();
+    AlignViewportI av = af.getViewport();
     AlignmentI al = av.getAlignment();
 
     /*
@@ -344,7 +346,7 @@ public class AlignFrameTest
   @Test(groups = "Functional")
   public void testColourThresholdActions()
   {
-    AlignViewport av = af.getViewport();
+    AlignViewportI av = af.getViewport();
     AlignmentI al = av.getAlignment();
 
     /*
@@ -513,7 +515,7 @@ public class AlignFrameTest
   @Test(groups = "Functional")
   public void testNewView_colourThresholds()
   {
-    AlignViewport av = af.getViewport();
+    AlignViewportI av = af.getViewport();
     AlignmentI al = av.getAlignment();
 
     /*
@@ -578,7 +580,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 959abb0..977e901 100644 (file)
@@ -27,6 +27,7 @@ import static org.testng.AssertJUnit.assertNotSame;
 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;
@@ -46,6 +47,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 +70,7 @@ public class AlignViewportTest
 
   AlignmentI al;
 
-  AlignViewport testee;
+  AlignmentViewport testee;
 
   @BeforeClass(alwaysRun = true)
   public static void setUpBeforeClass() throws Exception
@@ -397,7 +399,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();
@@ -426,8 +428,9 @@ 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.getAlignmentGapAnnotation(),
+            "Preference did not disable occupancy row.");
     int c = 0;
     for (AlignmentAnnotation aa : av.getAlignment().findAnnotations(null,
             null, "Occupancy"))
@@ -441,7 +444,8 @@ 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.getAlignmentGapAnnotation(),
+            "Preference did not enable occupancy row.");
     c = 0;
     for (AlignmentAnnotation aa : av.getAlignment().findAnnotations(null,
             null, av.getAlignmentGapAnnotation().label))
@@ -465,7 +469,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 bf961d8..9a09ce1 100644 (file)
@@ -240,6 +240,7 @@ public class PopupMenuTest
     // PDB.secondary structure on Sequence0
     AlignmentAnnotation annotation = new AlignmentAnnotation(
             "secondary structure", "", 0);
+    annotation.annotations = new Annotation[] { new Annotation(2f) };
     annotation.setCalcId("PDB");
     seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation);
     if (addToSequence)
@@ -254,6 +255,7 @@ public class PopupMenuTest
     // PDB.Temp on Sequence1
     annotation = new AlignmentAnnotation("Temp", "", 0);
     annotation.setCalcId("PDB");
+    annotation.annotations = new Annotation[] { new Annotation(2f) };
     seqs.get(1).getDatasetSequence().addAlignmentAnnotation(annotation);
     if (addToSequence)
     {
@@ -267,6 +269,7 @@ public class PopupMenuTest
     // JMOL.secondary structure on Sequence0
     annotation = new AlignmentAnnotation("secondary structure", "", 0);
     annotation.setCalcId("Jmol");
+    annotation.annotations = new Annotation[] { new Annotation(2f) };
     seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation);
     if (addToSequence)
     {
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 968901f..84bd714 100644 (file)
@@ -1,5 +1,9 @@
 package jalview.io;
 
+import static org.testng.Assert.assertEquals;
+
+import jalview.bin.Cache;
+
 import org.junit.Assert;
 import org.testng.annotations.Test;
 
@@ -19,4 +23,34 @@ public class FileLoaderTest
     // Data source type expected to be DataSourceType.URL
     Assert.assertEquals(DataSourceType.URL, fileLoader.protocol);
   }
+
+  @Test(groups = "Functional")
+  public void testUpdateRecentlyOpened()
+  {
+    // ensure properties file is read-only
+    Cache.loadProperties("test/jalview/io/testProps.jvprops");
+
+    String recent = "RECENT_FILE";
+    Cache.removeProperty(recent);
+
+    String prop = FileLoader.updateRecentlyOpened("a/b/c",
+            DataSourceType.FILE);
+    assertEquals(prop, "a/b/c");
+
+    prop = FileLoader.updateRecentlyOpened("d/e/f", DataSourceType.FILE);
+    assertEquals(prop, "d/e/f\ta/b/c");
+
+    // revisiting a file moves it to the top of the list
+    prop = FileLoader.updateRecentlyOpened("a/b/c", DataSourceType.FILE);
+    assertEquals(prop, "a/b/c\td/e/f");
+    
+    // history list is limited to the most recent 11 items
+    for (int i = 0; i < 20; i++)
+    {
+      prop = FileLoader.updateRecentlyOpened(String.format("%d.fa", i),
+              DataSourceType.FILE);
+    }
+    assertEquals(prop,
+            "19.fa\t18.fa\t17.fa\t16.fa\t15.fa\t14.fa\t13.fa\t12.fa\t11.fa\t10.fa\t9.fa");
+  }
 }
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/HMMAlignmentTest.sto b/test/jalview/io/HMMAlignmentTest.sto
new file mode 100644 (file)
index 0000000..f0f1f4a
--- /dev/null
@@ -0,0 +1,16 @@
+# STOCKHOLM 1.0
+#=GS Q7XA98_TRIPR/1-152   DR UNIPROT ; Q7XA98 
+#=GS FER1_PEA/1-149       DR UNIPROT ; P09911 
+#=GS Q93XJ9_SOLTU/1-144   DR UNIPROT ; Q93XJ9 
+#=GS FER_CAPAN/1-144      DR UNIPROT ; Q9ZTS2 
+#=GS FER1_SOLLC/1-144     DR UNIPROT ; Q43517 
+#=GS FER_CAPAA/1-97       DR UNIPROT ; P83527 
+FER_CAPAA/1-97             ------------------------------------------------------------------------ASYKVKLITPDGPIEFDCPDDVYILDQAEEAGHDLPYSCRAGSCSSCAGKIAGGAVDQTDGNFLDDDQLEEGWVLTCVAYPQSDVTIETHKEAELVG-
+FER_CAPAN/1-144            MA------SVSATMISTSFMPRKPAVTSL-KPIPNVGE--ALFGLKS-A--NGGKVTCMASYKVKLITPDGPIEFDCPDNVYILDQAEEAGHDLPYSCRAGSCSSCAGKIAGGAVDQTDGNFLDDDQLEEGWVLTCVAYPQSDVTIETHKEAELVG-
+FER1_SOLLC/1-144           -------------MA------SISGTMISTSFLPRKPAVTSL-KAISNVGE--ALFGLKS-G--RNGRITCMASYKVKLITPEGPIEFECPDDVYILDQAEEEGHDLPYSCRAGSCSSCAGKVTAGSVDQSDGNFLDEDQEAAGFVLTCVAYPKGDVTIETHKEEELTA-
+Q93XJ9_SOLTU/1-144         --------MA------SISGTMISTSFLPRKPVVTSL-KAISNVGE--ALFGLKS-G--RNGRITCMASYKVKLITPDGPIEFECPDDVYILDQAEEEGHDLPYSCRAGSCSSCAGKVTAGTVDQSDGKFLDDDQEAAGFVLTCVAYPKCDVTIETHKEEELTA-
+FER1_PEA/1-149             -------------MATT---PALYGTAVSTSFLRTQPMPMSV-TTTKAFSN--GFLGLKT-SLKRGDLAVAMASYKVKLVTPDGTQEFECPSDVYILDHAEEVGIDLPYSCRAGSCSSCAGKVVGGEVDQSDGSFLDDEQIEAGFVLTCVAYPTSDVVIETHKEEDLTA-
+Q7XA98_TRIPR/1-152         -------------MATT---PALYGTAVSTSFMRRQPVPMSV-ATTTTTKAFPSGFGLKSVSTKRGDLAVAMATYKVKLITPEGPQEFDCPDDVYILDHAEEVGIELPYSCRAGSCSSCAGKVVNGNVNQEDGSFLDDEQIEGGWVLTCVAFPTSDVTIETHKEEELTA-
+#=GC SS_cons                                                                              EEE    EEEEEEEE    HHHHH          e    e  e EE     EE          HHHH E   e  EE   EEEEE         
+#=GC Iron_Sulphur_Contacts -------------------------------------------------------------------------------------------------e----e--e-----------------------------e---------------------
+//
diff --git a/test/jalview/io/HMMAlignmentTestHMM.hmm b/test/jalview/io/HMMAlignmentTestHMM.hmm
new file mode 100644 (file)
index 0000000..649f5f9
--- /dev/null
@@ -0,0 +1,478 @@
+HMMER3/f [3.2 | June 2018]
+NAME  Alignment_HMM
+LENG  152
+ALPH  amino
+RF    no
+MM    no
+CONS  yes
+CS    no
+MAP   yes
+DATE  Fri Jun  7 14:44:10 2019
+NSEQ  6
+EFFN  2.071289
+CKSUM 2312940853
+STATS LOCAL MSV      -10.2278  0.70920
+STATS LOCAL VITERBI  -10.8843  0.70920
+STATS LOCAL FORWARD   -4.3996  0.70920
+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.41432  3.67931  2.75921  2.60121  3.50018  2.76530  3.83614  2.93106  2.71371  2.66765  3.66760  3.24838  3.26026  3.17831  3.19279  2.51076  2.65615  2.59873  5.09464  3.62512
+          2.68544  4.42237  2.77531  2.73135  3.46365  2.40524  3.72506  3.29365  2.67752  2.69366  4.24294  2.90358  2.73751  3.18158  2.89812  2.37898  2.77531  2.98530  4.58488  3.61515
+          0.78057  1.55851  1.10441  0.67815  0.70837  0.00000        *
+      1   2.59800  4.39329  3.63625  3.18787  3.71456  3.43841  4.11392  3.03068  3.09157  2.71409  1.85445  3.48425  4.00395  3.44434  3.39575  1.59145  2.94832  2.79270  5.21434  3.95539      9 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.02133  4.25401  4.97636  0.61958  0.77255  0.98598  0.46693
+      2   1.50579  4.32755  4.18645  3.78216  3.88559  3.56425  4.59767  2.41074  3.70275  2.69336  3.78707  3.89382  4.19613  3.99133  3.94010  2.99086  3.05698  1.28977  5.52248  4.31320     10 v - - -
+          2.68550  4.42242  2.77537  2.73141  3.46371  2.40530  3.72512  3.29371  2.67758  2.69372  4.24707  2.90364  2.73757  3.18164  2.89818  2.37841  2.77443  2.98536  4.58494  3.61520
+          0.90209  1.16285  1.26696  1.01535  0.44985  0.39057  1.12909
+      3   3.42707  4.91214  4.61207  4.26925  3.52422  4.22326  4.89422  2.75377  4.00666  2.06722  0.68834  4.47974  4.70831  4.36739  4.15005  3.81331  3.75358  2.81142  5.41119  4.20659     14 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.01938  4.34894  5.07129  0.61958  0.77255  0.90177  0.52062
+      4   1.43643  4.42503  4.31312  3.86585  3.75424  3.86050  4.64018  1.40277  3.76673  2.49922  3.64972  4.05060  4.39156  4.05997  3.99981  3.25891  3.19718  2.11006  5.45161  4.24039     15 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.14665  4.34894  2.09167  0.61958  0.77255  0.90177  0.52062
+      5   2.37098  4.31475  3.56770  3.24979  4.37798  3.10030  4.31086  3.75066  3.26247  3.47251  4.31621  3.42494  3.83407  3.57718  3.57680  1.30947  1.53387  3.24501  5.72919  4.50336     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.02198  4.22428  4.94663  0.61958  0.77255  0.54114  0.87248
+      6   2.50652  4.44141  3.83949  3.54853  4.61304  3.23185  4.57545  3.99871  3.56049  3.72110  4.55726  3.64948  3.99392  3.85973  3.84879  1.49216  1.01986  3.44946  5.96659  4.76085     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.24086  4.47354  1.59630  0.61958  0.77255  0.76398  0.62700
+      7   2.65517  4.36127  3.81549  3.38335  3.69064  3.54500  4.25486  1.58799  3.30272  2.65201  3.68407  3.64162  4.10535  3.63002  3.58335  1.61226  3.00284  2.44965  5.24306  3.98781     18 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.02133  4.25401  4.97636  0.61958  0.77255  0.98598  0.46693
+      8   2.74723  4.45808  3.83003  3.43336  1.55716  3.57739  4.01030  3.12129  3.39844  2.75883  3.78862  3.64312  4.13759  3.66183  3.66464  1.60155  3.09781  2.89427  4.64509  3.10366     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.02133  4.25401  4.97636  0.61958  0.77255  0.98598  0.46693
+      9   2.65532  4.43699  3.65638  3.26130  3.78761  1.68622  4.19753  3.09268  3.18548  2.76736  1.66329  3.54773  4.04431  3.53861  3.47551  2.87376  3.01742  2.85730  5.28180  4.04464     20 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.02133  4.25401  4.97636  0.61958  0.77255  0.55834  0.84900
+     10   2.62413  4.55150  3.73217  3.46502  4.58891  3.32606  4.53947  3.93771  3.48022  3.66044  4.54532  3.64966  1.08714  3.81713  3.77509  2.80225  1.57704  3.45878  5.93284  4.72852     21 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.01709  4.47354  5.19589  0.61958  0.77255  0.51701  0.90709
+     11   1.99709  4.68552  3.40260  2.84388  3.94615  3.60689  3.90388  3.32023  2.73340  2.98773  2.29384  3.29447  4.03205  3.12399  2.03393  2.35985  2.99523  3.04365  5.29921  4.03061     22 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     12   3.03612  4.58206  4.17469  3.58665  3.60032  4.09338  4.33760  1.51772  1.94651  1.71212  3.50362  3.91731  4.43832  3.70785  3.50867  3.39096  3.26453  2.43051  5.23091  4.03724     23 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     13   2.76197  4.70799  3.41034  2.96484  3.84310  3.56022  4.02290  3.51807  2.97071  3.16868  4.04204  3.37800  2.07618  3.30589  3.36146  1.59778  3.07503  3.20545  5.27554  2.20871     24 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     14   1.42932  4.46589  4.02364  3.69643  4.72988  1.43294  4.68906  4.13282  3.71549  3.83309  4.64260  3.74322  4.03851  3.97444  4.00639  2.72003  1.63454  3.53847  6.07503  4.89460     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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     15   2.63382  4.43500  3.98903  3.52691  4.05377  3.47381  4.41118  3.21360  3.46955  3.09630  4.00516  3.71495  4.11115  3.75748  3.76367  1.74048  1.56254  1.69711  5.50933  4.30015     26 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     16   1.97870  4.28154  4.12278  3.55312  2.14335  3.81420  4.17500  2.68382  3.44988  2.41995  2.61784  3.79310  4.21338  3.68984  3.66833  3.11084  1.96434  2.49922  4.91664  3.71472     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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     17   2.91846  4.34842  4.48199  3.90988  3.46317  4.07572  4.44144  1.98330  3.78456  1.67828  3.41359  4.10010  4.43748  4.00384  3.95399  2.01206  3.16092  1.64497  5.07625  3.88829     28 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     18   2.70635  4.56892  3.60528  3.14080  3.96671  3.53723  4.15403  3.33644  3.10057  1.82443  3.93202  3.49380  2.11690  3.43662  3.45226  1.62468  3.04334  3.04998  5.39218  4.13558     29 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.26457  4.57201  1.50451  0.61958  0.77255  0.62415  0.76726
+     19   2.81401  4.82005  3.48128  2.94818  4.34473  3.53963  3.92028  3.69738  2.45527  3.31575  4.19707  3.33652  4.04563  3.10077  1.62480  2.90920  1.49986  3.36258  5.52959  4.29493     30 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.01981  4.32725  5.04960  0.61958  0.77255  0.42245  1.06549
+     20   2.99742  5.17558  3.29695  2.86766  4.77169  3.64255  3.98284  4.20460  1.15211  3.71930  4.54717  3.31939  4.14896  3.12831  2.80934  1.59962  3.28379  3.79417  5.81941  4.54197     31 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     21   3.28763  4.90910  4.31235  3.99239  1.36983  4.02580  4.37777  3.48169  3.95787  2.96396  4.13543  4.15449  1.08518  4.20039  4.16663  3.51751  3.64052  3.33099  4.84797  3.27396     32 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     22   3.45018  4.70771  5.41218  4.85806  3.55317  4.84496  5.27184  1.41698  4.72877  1.42021  2.43827  4.98314  5.05481  4.81112  4.77841  4.21177  3.68367  1.42720  5.55642  4.46185     33 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     23   2.82485  4.73326  3.55705  3.00955  4.05482  3.65786  4.00613  3.34731  2.73677  3.06317  3.96177  3.42018  1.80573  3.23126  2.02314  2.96454  3.09977  1.95730  5.39957  4.14889     34 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     24   2.86127  5.09016  3.19616  2.69781  4.52201  3.59071  3.86031  3.94606  2.49967  3.49458  4.30305  1.96704  4.04133  2.99863  1.96172  2.88186  1.74316  3.56959  5.66035  4.34483     35 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     25   2.78170  4.95829  3.16704  2.62944  4.23097  3.58469  3.79757  3.63325  2.16991  3.23781  4.05928  3.13605  3.98936  2.12578  2.95429  2.00470  3.01690  2.13727  5.47298  4.15357     36 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     26   2.74867  4.60831  3.61740  3.20842  4.05654  1.87017  4.23901  3.42440  3.19407  1.83184  4.02720  3.54846  1.75260  3.52860  3.53526  2.92904  3.10347  3.12934  5.47730  4.23070     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.24245  4.57201  1.58496  0.61958  0.77255  0.62415  0.76726
+     27   2.23893  4.60373  3.28448  1.87774  3.79882  3.57859  3.83870  3.03021  2.72644  2.79800  2.80144  3.21864  3.97823  3.06477  3.13889  2.82027  2.92566  2.31720  5.19891  3.92417     38 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.34327  4.34894  1.28144  0.61958  0.77255  0.43345  1.04488
+     28   2.73943  4.82202  3.20350  2.68202  4.15055  3.52581  3.79474  3.47895  1.71004  3.13955  3.99838  3.15504  2.24076  2.96517  2.84990  2.80694  2.99350  2.43471  5.40910  4.11885     39 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.01981  4.32725  5.04960  0.61958  0.77255  0.92238  0.50679
+     29   1.67523  4.32939  3.80070  3.28713  3.65556  3.52435  4.14641  2.82922  3.20444  2.62909  2.04920  3.56786  4.04881  3.50886  3.50296  2.86733  2.23962  2.60434  5.15734  3.94638     40 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.01981  4.32725  5.04960  0.61958  0.77255  0.42245  1.06549
+     30   1.66814  4.43166  3.95026  3.47077  3.91143  3.54985  4.34218  1.84764  3.41576  2.94090  3.86903  3.70285  4.13774  3.70337  3.71262  1.58997  3.04021  2.78308  5.38688  4.17260     41 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     31   2.86839  4.40063  4.28613  3.75197  3.53211  3.91378  4.39907  2.56140  3.63254  1.42290  3.49235  3.96842  4.35205  3.89101  3.84593  1.98860  3.14663  1.72465  5.13588  3.93489     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.33933  4.57201  1.28224  0.61958  0.77255  0.62415  0.76726
+     32   2.99338  4.73521  3.52318  3.19423  1.49578  3.74751  3.84834  3.30385  3.23971  2.88691  3.93859  1.69947  4.23548  3.52506  3.56009  3.13754  3.28417  3.09751  4.46980  2.84938     43 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.02133  4.25401  4.97636  0.61958  0.77255  0.39057  1.12909
+     33   2.26113  4.65266  3.39149  2.85535  3.96561  2.14052  3.94035  3.32256  2.32255  3.01451  3.87297  3.29920  4.01793  3.16391  3.22857  2.83216  2.44156  2.03814  5.33010  4.05751     44 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     34   2.14527  4.45044  3.76875  3.26603  3.85788  2.04177  4.18979  3.17104  3.21967  1.81090  3.81461  3.56903  4.08500  3.51989  3.54833  2.88152  1.96723  2.89522  5.29995  4.07724     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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     35   2.77531  5.06924  3.07796  1.89721  4.35250  3.56090  3.75513  2.86917  1.82937  3.33902  4.13804  3.06897  3.95918  2.88565  2.93068  2.78088  2.17797  3.41042  5.54533  4.19589     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.24245  4.57201  1.58496  0.61958  0.77255  0.62415  0.76726
+     36   2.66334  4.78591  3.14690  2.69736  4.34791  3.40164  3.87711  3.75678  2.10710  3.36111  4.18006  3.15163  3.92504  3.04074  3.00575  1.44108  2.29363  3.36678  5.57460  4.27063     47 s - - -
+          2.68590  4.42232  2.77527  2.73130  3.46361  2.40520  3.72502  3.29361  2.67748  2.69362  4.24697  2.90308  2.73747  3.18154  2.89808  2.37894  2.77488  2.98526  4.58484  3.61510
+          0.44576  1.04019  5.07129  0.13971  2.03720  0.43345  1.04488
+     37   1.35032  4.33598  4.11743  3.57274  2.66462  3.74950  4.26894  2.70612  3.48547  2.58049  3.54278  3.80339  4.21776  3.73820  3.72893  3.07578  2.40333  2.07300  5.08335  3.87699     49 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.26457  4.57201  1.50451  0.61958  0.77255  0.62415  0.76726
+     38   2.67849  4.67202  3.20606  2.69337  3.93262  2.63512  3.80028  3.31587  2.17250  1.96311  3.82914  3.16211  3.94141  3.00575  3.00084  2.28900  2.93113  3.03056  5.26473  3.98290     50 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.01981  4.32725  5.04960  0.61958  0.77255  0.92238  0.50679
+     39   2.23745  4.71916  3.05672  2.16980  2.23785  3.50580  3.78395  3.31902  2.66523  2.97723  3.83443  2.49003  3.93379  2.99259  3.10154  2.77864  2.93862  3.03813  5.25364  3.93663     51 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.29014  4.32725  1.43280  0.61958  0.77255  0.42245  1.06549
+     40   2.71194  4.71147  3.14073  2.76488  2.63325  1.94411  3.91859  3.50545  2.86219  3.15174  4.02297  1.82298  3.98451  3.17614  3.28134  2.81220  3.01803  3.18804  5.26894  3.87083     52 n - - -
+          2.68618  4.42225  2.77519  2.73123  3.46354  2.40513  3.72494  3.29354  2.67741  2.69355  4.24690  2.90347  2.73739  3.18146  2.89801  2.37887  2.77519  2.98518  4.58477  3.61503
+          0.01895  4.37135  5.09369  0.61958  0.77255  0.87955  0.53609
+     41   2.64945  4.49564  3.49208  3.06414  3.88051  1.81354  4.08661  3.23766  3.04151  1.74255  3.84911  3.42067  2.61702  3.37781  3.38586  2.83194  2.98495  2.96040  5.30850  4.06003     53 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.01895  4.37135  5.09369  0.61958  0.77255  0.44572  1.02266
+     42   2.20625  4.93221  3.17339  2.72120  4.55189  1.72555  3.94981  3.99413  1.81667  3.55820  4.34814  3.19358  3.98997  3.09380  3.14134  2.24894  3.05082  3.55894  5.74349  4.41072     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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     43   2.73118  4.74977  3.26283  2.70881  2.98752  2.82347  3.82752  3.34686  1.92589  2.48911  3.84846  3.19660  3.99345  3.02672  3.10018  2.03919  2.96671  3.06691  5.29037  3.99373     55 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.24245  4.57201  1.58496  0.61958  0.77255  0.62415  0.76726
+     44   3.21892  4.54748  4.94678  4.39384  1.84065  4.45647  4.69231  2.23828  4.25181  1.55834  3.19076  4.52046  4.72563  4.36468  4.33750  3.79737  3.45238  1.39236  5.03910  3.75691     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.01938  4.34894  5.07129  0.61958  0.77255  0.43345  1.04488
+     45   2.63358  4.56206  3.94281  3.76669  4.90587  0.86987  4.83032  4.31802  3.87414  4.03413  4.86498  3.81723  4.11786  4.13859  4.13012  2.82336  1.52160  3.69008  6.22345  5.06760     57 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.24245  4.57201  1.58496  0.61958  0.77255  0.62415  0.76726
+     46   3.01864  1.79566  4.69259  4.19257  3.41038  4.04365  4.66782  2.43586  3.98238  1.14404  3.36027  4.28885  4.50409  4.22027  4.10902  3.45690  3.32610  2.36331  5.19668  3.99182     58 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.01938  4.34894  5.07129  0.61958  0.77255  0.90177  0.52062
+     47   2.96377  4.89266  3.53249  2.95386  4.04795  3.74350  3.88142  3.34726  1.40052  2.91530  1.93101  3.37640  4.14009  3.07637  2.67530  3.06693  3.18523  3.14375  5.36699  4.12971     59 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.01938  4.34894  5.07129  0.61958  0.77255  0.43345  1.04488
+     48   1.77870  4.80105  3.33239  2.80291  4.36522  3.47131  3.95619  3.78270  2.73318  3.38875  4.19761  3.24889  3.98437  3.11824  1.99740  1.90727  2.40269  3.38967  5.61455  4.31002     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.21961  4.57201  1.67756  0.61958  0.77255  0.62415  0.76726
+     49   2.60823  4.64033  3.22015  2.80894  4.20933  3.36458  3.98710  3.59284  2.85357  3.27469  4.11620  1.86137  3.93152  3.18866  3.26591  1.65119  2.95563  2.38198  5.53276  4.23147     61 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.01895  4.37135  5.09369  0.61958  0.77255  0.44572  1.02266
+     50   2.74410  4.67335  3.45404  3.06703  3.90844  1.64792  4.12669  3.60477  3.11681  3.26108  4.13393  3.44191  4.09025  3.43093  3.49590  1.86622  3.09650  3.26485  5.35022  1.97056     62 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.11556  4.57201  2.31473  0.61958  0.77255  0.62415  0.76726
+     51   2.95370  5.14232  3.38998  2.75626  4.47479  3.70680  3.76608  3.85318  1.57496  2.58800  4.21663  3.22595  4.07617  2.90174  1.75899  2.96747  2.46355  3.52788  5.54040  4.28024     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.01709  4.47354  5.19589  0.61958  0.77255  0.76398  0.62700
+     52   2.97237  4.48471  4.17487  3.61038  3.68717  4.08286  4.40175  1.59509  2.09243  2.51779  3.58882  3.93788  4.44245  3.78487  3.66371  3.38387  3.21319  1.46639  5.29622  4.08064     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.01709  4.47354  5.19589  0.61958  0.77255  0.51701  0.90709
+     53   3.16272  5.37499  3.59177  2.92070  4.82565  3.84597  3.83774  4.18579  1.50049  3.63868  4.47141  3.36065  4.21246  2.96157  1.48253  3.15294  1.98320  3.83770  5.70684  4.49260     65 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     54   2.69126  2.25915  3.80687  3.28606  3.66656  2.21575  4.13449  3.01259  3.21697  1.80809  3.65267  2.64888  4.11014  3.51421  3.51970  2.94231  2.98955  2.76835  5.12838  3.90654     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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     55   2.75976  4.54905  2.30455  2.95518  3.70676  2.79648  3.96957  2.00953  2.95066  2.74085  2.27446  3.39166  4.08996  3.25986  3.33214  2.95036  2.99901  2.76002  5.14787  3.89753     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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     56   1.92745  4.55633  3.54968  2.99110  3.77370  3.65270  3.97236  3.10509  2.88439  2.02402  3.71145  3.40529  4.07525  3.24934  2.56281  2.91984  1.98149  2.86151  5.18773  3.94368     68 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     57   1.83228  4.53823  3.61230  3.10354  4.02012  3.49038  4.12836  2.50681  3.07752  3.08124  3.94943  3.45725  2.07017  3.39222  3.45240  1.83561  2.99081  3.04929  5.41506  4.16867     69 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     58   2.75895  4.66749  2.12963  2.81059  3.81488  3.63897  3.90096  3.17855  2.82626  2.89854  3.77788  3.28020  4.04584  3.14685  3.24113  2.89220  2.45960  2.10817  5.21741  2.34581     70 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     59   1.87134  2.92490  3.41990  2.89562  4.22753  2.00930  4.00910  3.62340  1.87199  3.26968  4.10116  3.31508  4.00325  3.20209  3.23675  2.78496  2.99855  3.26410  5.53516  4.25405     71 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.01548  4.57201  5.29435  0.61958  0.77255  0.62415  0.76726
+     60   2.89677  4.42989  4.26135  3.71893  3.52156  3.94729  4.39343  2.57065  3.59726  2.35872  1.80824  3.96209  2.13460  3.86316  3.82140  3.27132  3.16554  1.68431  5.14387  3.95469     72 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.01548  4.57201  5.29435  0.61958  0.77255  0.40804  1.09349
+     61   1.57565  4.67644  3.61371  3.07202  3.92167  3.75428  4.06548  1.97069  1.96866  2.90804  3.83592  3.49072  4.17868  3.32201  3.23603  3.03786  3.11158  2.81687  5.33764  4.09102     73 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     62   2.78306  4.91407  3.16080  1.90266  4.17861  3.59010  3.85833  3.57055  2.67830  2.17323  4.03601  3.16932  4.01281  3.02684  3.12616  1.86668  2.50737  3.25963  5.47226  4.15166     74 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     63   3.70553  4.96355  5.18038  4.77967  1.51175  4.68042  4.04025  1.78081  4.59062  2.70856  3.92100  4.53151  4.97996  4.54894  4.56550  4.02683  3.92721  3.14972  4.19952  1.17802     75 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     64   2.92406  5.37226  1.90980  2.50543  4.72545  3.56703  3.85582  4.19183  1.50834  3.69445  4.47134  3.05483  4.03152  2.97675  3.09023  2.88240  2.07165  3.77594  5.84089  4.43845     76 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     65   2.78562  2.01948  4.55150  4.07045  3.82424  3.73349  4.63777  2.73929  3.93362  2.80343  3.79417  4.09169  2.08695  4.16452  4.09382  3.13564  3.15495  1.28567  5.38169  4.19434     77 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     66   3.00177  5.48795  1.87629  2.49660  4.83835  3.57687  3.90289  4.32338  1.47116  3.80689  4.58836  3.05453  2.14999  3.02804  3.16908  2.94349  3.25201  3.89612  5.94044  4.52232     78 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     67   2.97021  5.07355  1.83355  2.70799  4.34142  2.06896  4.05903  3.73788  2.99051  1.56224  4.26678  3.22685  4.13776  3.25977  3.46241  3.01746  3.25070  3.43787  5.68476  4.34458     79 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     68   2.80435  4.51738  3.70485  3.17345  3.71222  3.76651  4.10838  1.80977  3.12705  2.73704  3.66708  2.15696  2.34690  3.43898  3.47179  3.04517  3.05888  2.24183  5.18327  3.94621     80 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     69   3.21770  4.57086  4.97188  4.44662  3.86947  4.49942  5.05720  1.47430  4.33664  2.56546  3.72458  4.61110  4.86186  4.58040  4.51238  3.86070  1.54232  1.34555  5.64266  4.43926     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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     70   2.95708  5.14521  2.99403  1.83121  4.19063  3.63668  3.92702  3.82818  2.78051  3.41772  4.26662  3.17833  1.74182  3.12106  3.22848  2.97355  3.20630  3.50738  5.52563  2.17177     82 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     71   2.81050  4.79261  2.28753  2.03040  2.37706  3.65659  3.90550  2.14897  2.80356  2.99311  3.87365  3.24848  4.06373  3.12317  3.23928  2.91155  3.04567  3.04162  5.32210  4.01594     83 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     72   2.93437  5.03828  3.04311  1.83946  4.30552  1.65755  3.99888  3.68879  2.85177  1.98910  4.20097  3.22855  4.11576  3.18781  3.28771  2.98470  3.19963  3.39021  5.62197  4.29753     84 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     73   2.73902  2.32080  1.99570  2.81784  4.32430  3.51217  4.01811  3.72234  2.87487  3.36392  4.18957  3.27606  1.98571  3.19798  3.31847  2.82453  2.44358  3.35784  5.62280  4.31413     85 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     74   2.87088  4.85397  3.36105  2.86591  4.06081  3.69200  3.97062  2.23427  2.75935  3.04437  3.96579  3.33519  2.30215  1.57203  3.13528  2.97368  3.12105  3.13247  5.42664  4.13968     86 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     75   1.84740  5.71599  1.70450  1.29585  5.04192  3.56048  4.02374  4.54881  2.96239  4.03556  4.84247  3.02480  4.13163  3.16811  3.53263  3.05937  3.42628  4.10758  6.18823  4.70375     87 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     76   3.06953  5.41519  1.80939  1.67828  1.68690  3.60061  3.98096  4.10134  2.91401  3.66294  4.51080  3.08865  4.12438  3.15808  3.43938  3.03000  3.32748  3.75306  5.79034  4.33444     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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     77   3.03870  5.47436  1.90526  1.29548  4.76783  3.57223  3.95900  4.16399  2.84250  3.75797  4.57501  3.05039  4.09259  3.10162  3.37273  2.98560  3.29722  2.13649  5.96102  4.53077     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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     78   1.74787  1.64658  4.29549  3.78786  3.51816  3.70291  4.33651  2.97775  3.65907  2.75066  3.68827  3.90525  4.24339  3.90389  3.85120  3.07083  3.08999  2.74475  5.04806  2.07593     90 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     79   2.75948  4.56996  3.79425  3.38335  4.06237  1.91193  4.35624  1.91599  3.36983  3.10692  4.02732  3.67147  1.55829  3.68001  3.68915  2.97218  3.12763  3.01951  5.50730  4.27905     91 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     80   2.84361  5.11662  1.88614  2.55687  4.33854  3.57668  2.26268  3.81219  2.65486  2.21008  4.20214  3.09171  4.01205  2.98715  3.13133  2.39282  3.08430  3.46799  5.59000  4.21533     92 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     81   4.05062  6.09585  0.25016  3.16592  5.63180  4.01455  4.88658  5.44743  4.14657  4.91966  5.97362  3.74150  4.71639  4.16606  4.71915  3.96503  4.42100  5.01815  6.60717  5.45534     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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     82   3.04959  4.58334  4.21832  3.66721  3.55820  4.11355  4.41299  2.59646  3.48731  1.61108  3.47616  3.98523  4.47164  2.16526  3.73518  3.41507  3.28754  1.39698  5.22079  4.02388     94 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     83   1.82715  4.61744  3.67020  3.22382  3.72690  3.63976  4.15441  3.35282  3.20066  3.04408  3.94999  3.56979  2.08621  3.51946  3.54139  2.98757  3.12307  3.07635  5.20580  1.61753     95 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     84   2.90062  4.56201  3.71550  2.09080  3.49327  3.86304  4.08810  1.59101  3.18089  2.67620  3.64335  3.61449  4.25289  3.49651  3.50065  3.15073  3.13529  2.70012  5.01515  2.15048     96 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     85   2.86216  4.89215  3.16897  1.91855  4.11409  3.63867  3.95829  3.48538  2.81326  1.65439  4.02074  3.25472  4.09032  3.16123  3.23386  1.94184  3.11683  3.21094  5.46706  4.16201     97 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     86   3.02911  2.20051  1.43610  1.72118  4.75550  3.57025  3.97871  4.20820  2.86443  3.76403  4.57605  3.07440  4.09745  3.12563  3.38808  2.98631  3.29630  3.81727  5.95041  4.53316     98 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     87   2.95229  5.31841  3.20763  2.65443  4.67641  2.24293  2.35827  4.11573  2.37176  3.59677  4.38392  3.16553  4.07082  2.08202  1.87641  2.92797  3.16779  3.72847  5.70861  4.38173     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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     88   0.89304  4.83593  3.52252  3.21237  4.28827  3.57365  1.98662  3.92815  3.18973  3.57384  4.45958  3.56834  4.20309  3.58992  3.52232  3.01049  3.26669  3.54231  5.67260  4.31414    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     89   3.32897  5.98995  1.59036  1.21041  5.29223  1.85016  4.13193  4.84216  3.17456  4.29824  5.13981  3.02434  4.20540  3.29334  3.80439  3.19395  3.62119  4.37723  6.44195  4.89720    101 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     90   2.86612  5.04422  3.04967  1.53080  4.31043  3.59969  3.90678  3.70979  2.72310  2.13413  4.17356  3.16516  4.05445  3.07158  3.17171  1.93423  3.11943  3.39271  5.59276  4.25151    102 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     91   2.33839  2.33319  3.66936  2.51274  3.71047  3.68123  4.05819  3.02481  3.07985  2.77576  3.67017  3.50531  2.35114  3.38402  3.43065  2.95965  3.00527  2.02342  5.15389  3.92054    103 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     92   2.77841  4.71648  3.50561  3.12657  4.00129  1.51312  4.19518  3.69627  3.18257  3.34991  4.21891  3.49374  4.13113  3.49456  3.56191  1.76331  3.14172  3.34204  5.43765  2.07352    104 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     93   2.80900  4.65790  3.51214  3.01139  3.79431  3.68037  2.38933  2.16836  2.94391  2.94776  3.84277  3.43128  4.12697  3.30452  3.30672  1.48154  3.07555  2.99103  5.22365  3.91367    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     94   3.04847  1.50371  1.61592  2.10236  4.66715  3.58851  4.05112  4.08665  2.97076  3.69723  4.53735  3.13921  4.13665  3.22062  3.48126  3.03480  3.33057  3.72643  5.91738  4.53055    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     95   1.88410  4.65574  3.78265  3.20892  3.82389  3.79819  4.09423  3.12221  2.89200  1.51545  3.75540  3.58503  4.21920  3.38078  2.03442  3.09778  3.14791  2.92061  5.27033  4.04785    107 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     96   1.54090  4.57715  3.92273  3.65745  4.90631  1.66510  4.74228  4.35275  3.75572  4.01671  4.81278  3.76174  1.32436  4.00941  4.06725  2.79701  3.13028  3.70679  6.22047  5.03095    108 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     97   2.97420  5.05368  3.30132  2.83355  4.07677  2.15834  3.92294  3.75113  1.76958  3.34315  4.20275  3.31006  4.15184  3.13365  2.98906  3.02497  3.21508  3.44631  5.40486  1.71904    109 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     98   2.82535  4.57572  4.10028  3.71301  4.03925  3.66632  4.58086  1.72884  3.64091  3.01747  4.04865  3.90026  4.29816  3.95980  3.90549  0.98108  3.22247  2.79320  5.58742  4.33006    110 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+     99   1.43514  0.82892  4.80681  4.58666  4.69417  3.39195  5.16406  3.80758  4.43086  3.75239  4.68183  4.17266  4.21161  4.63066  4.50594  2.88757  3.18548  3.35323  6.15457  5.03517    111 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    100   2.82498  4.95715  3.40974  2.94255  4.70228  1.94565  4.08107  4.14251  2.73685  3.69574  4.49749  3.36420  4.09658  3.23391  1.46522  1.83152  3.16614  3.68558  5.84898  4.56169    112 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    101   1.10475  4.52228  4.11576  3.83581  4.96435  1.64082  4.84380  4.42439  3.89199  4.08943  4.86937  3.83086  4.09259  4.12724  4.17193  1.57246  3.10246  3.72147  6.28518  5.11952    113 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    102   1.43394  1.83402  4.58768  4.30129  4.75045  1.21055  5.01466  4.12708  4.21833  3.87731  4.70556  4.01744  4.11929  4.41365  4.36995  2.77887  3.09436  3.53695  6.15056  5.02931    114 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    103   1.63449  4.47604  4.14466  3.71946  4.28385  3.44523  4.59529  3.45965  3.67241  3.33633  4.23051  3.81973  4.14313  3.94095  3.94969  1.28973  3.08609  1.71945  5.72686  4.53067    115 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    104   2.83251  1.48569  1.76496  3.05212  4.63546  1.87091  4.34311  4.05699  3.30285  3.71503  4.55202  3.45874  4.14769  3.56082  3.73402  2.94445  3.23212  3.61792  5.93755  4.65533    116 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    105   2.96957  5.32904  3.14366  2.65593  4.72494  3.66151  3.84186  4.16441  1.75186  3.64779  4.43821  3.16888  4.08411  1.93241  2.79580  1.59020  3.19856  3.76805  5.76348  4.43156    117 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    106   2.66373  4.49207  4.03296  3.57936  4.18285  3.48606  4.48323  3.36835  3.52695  3.23079  4.12951  3.75581  4.14350  3.81520  3.82610  1.34147  1.75798  1.80637  5.62511  4.41600    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    107   2.74792  1.62573  1.91234  3.05734  4.31516  3.50848  4.22275  3.63214  3.15497  3.36887  4.23026  3.44805  4.10111  3.45245  3.56167  2.88548  1.89159  3.28014  5.67623  4.40213    119 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    108   0.68941  4.56331  4.20169  4.04692  5.05279  1.58716  5.03141  4.47978  4.15844  4.19817  5.00681  3.95737  4.16246  4.36890  4.37009  2.84226  3.19149  3.77919  6.37750  5.25838    120 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    109   3.02964  5.08328  3.17150  3.12104  5.13170  0.81179  4.59407  4.73207  3.60754  4.31434  5.15959  1.65030  4.27627  3.83105  4.02354  3.11995  3.49284  4.12591  6.35429  5.05698    121 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    110   2.85780  4.78493  3.46807  2.92281  2.21689  3.71308  3.94679  3.34785  1.56806  3.01008  3.90816  3.37147  4.12450  3.18495  3.10090  2.97945  2.06570  3.09328  5.28703  3.97445    122 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    111   3.56792  4.79047  5.56843  5.05882  3.83185  5.08010  5.63680  1.72792  4.96256  1.47356  3.59353  5.21772  5.28003  5.11439  5.06846  4.48190  3.81459  0.88361  5.91262  4.77603    123 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    112   2.34885  4.88546  1.50680  2.76582  4.28202  3.57605  3.99821  3.49749  2.86169  3.28542  4.14261  3.25275  4.06485  3.17747  3.31619  2.88335  2.45367  2.13395  5.60583  4.28774    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    113   2.37560  5.43186  1.88002  2.44821  4.76975  2.31003  3.85108  4.26118  2.66530  3.74586  4.51061  2.44214  4.01416  2.00579  3.18288  2.86422  3.16817  3.82620  5.88838  4.45514    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    114   3.02825  5.34001  1.64973  2.62556  5.04958  1.43770  4.18261  4.55907  3.15840  4.08500  4.89492  3.15845  4.14205  3.34808  3.70413  1.79379  3.38532  4.04813  6.24427  4.81118    126 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    115   2.43421  5.39468  1.99800  2.11130  4.72686  3.53375  3.80066  4.21905  2.58750  3.69532  4.44801  2.47018  3.98139  1.98470  3.09824  2.34600  3.10833  3.78019  5.82949  4.40030    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    116   2.94597  4.44901  4.44561  3.93108  3.62623  2.15331  4.54520  2.49864  3.80946  1.67061  3.57798  4.11336  4.45736  4.06092  4.00094  3.35990  3.23101  1.30872  5.24560  4.04661    128 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    117   3.07108  5.65983  1.61666  1.64591  4.97722  3.55644  3.94110  4.49006  1.85258  3.95163  4.73218  2.37323  4.08443  3.06951  3.35115  2.98315  3.32751  4.04015  6.08373  4.61352    129 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    118   2.90641  5.14851  3.03065  1.82407  2.34336  3.62785  3.86089  3.81266  2.66227  3.36932  4.21751  3.14311  4.06155  1.65090  3.10716  2.91351  3.14323  3.49036  5.52105  4.11540    130 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    119   2.76255  4.86202  3.19852  2.29238  4.13565  2.23517  3.86729  3.53680  2.70242  2.16346  4.00273  3.18654  4.00924  3.04372  3.14909  2.07641  2.54383  3.22686  5.44173  4.12929    131 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    120   3.57941  5.58171  0.75523  3.12318  4.02169  3.96847  4.37908  4.42174  3.52990  3.92216  4.91170  3.63855  4.53554  3.76654  3.97529  3.57745  3.86789  4.12842  1.75169  3.95153    132 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    121   2.91174  5.02616  1.86612  2.75649  4.50983  1.54341  4.12514  3.82111  3.05693  3.54399  4.40141  3.25444  4.12333  3.31620  3.53368  2.97056  3.23532  1.93277  5.82328  4.48241    133 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    122   2.86459  5.20437  2.00723  2.52234  4.49985  3.55603  3.85351  3.95142  2.67319  2.15274  4.30753  2.15442  4.01247  2.99055  3.16622  2.05025  3.11283  3.57971  5.70819  4.32388    134 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    123   2.86858  4.64306  3.62963  3.12613  1.70785  3.76769  4.03967  3.15671  3.04812  2.80119  3.75818  3.52490  4.19369  2.11823  3.38968  3.05795  1.97932  2.94141  5.07338  3.71197    135 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    124   2.87729  2.25286  3.84987  2.10126  3.62200  3.85343  4.19223  2.84299  3.24572  1.47166  3.58556  3.69315  4.26287  3.56918  3.54313  3.15439  3.12814  2.66630  5.14969  3.92844    136 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    125   1.87554  4.89400  1.55330  2.83635  4.32557  3.59793  4.10822  3.41524  3.01358  3.31001  4.20357  3.31594  4.12580  3.30435  3.46699  2.95750  3.16753  1.90970  5.68921  4.37289    137 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    126   1.31978  5.65673  1.53971  2.00100  5.00455  3.56144  4.04702  4.49528  2.99731  4.00710  4.82437  3.04396  4.14090  3.19815  3.56394  3.06909  3.43192  4.06642  6.17533  4.70374    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    127   2.99154  5.46776  1.93424  1.79632  4.74629  2.13218  3.90636  4.24433  2.76518  3.75551  4.54564  3.02592  4.05721  3.04023  3.29236  2.93391  3.24309  3.83702  5.91396  2.21504    139 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    128   2.90782  4.87069  3.38284  2.90818  2.18962  3.72084  3.95729  3.47130  2.86207  3.05902  3.98760  3.36869  2.19368  1.63399  3.25068  3.00729  3.16046  3.21829  5.19587  3.77282    140 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    129   2.80387  4.50973  3.68288  2.53916  3.64508  3.79101  4.04638  2.09044  3.05762  2.30112  3.59386  3.52646  4.16714  2.16471  3.40576  3.04110  3.03585  1.93346  5.11678  3.88419    141 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    130   2.33816  4.92974  3.14216  1.79211  4.20735  3.58332  3.86460  3.60039  2.68643  2.17242  4.06142  3.16489  4.01325  3.03072  3.13839  1.97098  3.03629  3.28400  5.49619  4.17164    142 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    131   2.04954  5.30098  1.94774  2.15701  4.64724  2.73655  3.83132  4.12007  2.63294  3.63223  4.40230  3.02948  3.99372  2.95114  3.13793  2.82654  2.09314  3.70436  5.79378  4.38447    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    132   2.67461  1.98295  4.54536  4.13152  4.08175  1.38240  4.74089  3.14924  4.01069  3.12077  4.06082  4.04085  4.22311  4.23030  4.16807  2.96147  3.11654  1.64169  5.59063  4.41633    144 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    133   2.83984  4.25742  4.52040  3.93471  2.15049  3.96796  4.23092  2.63475  3.77248  2.37225  3.34682  4.03138  4.33444  3.94714  3.87337  3.27306  1.99292  1.78236  2.52955  3.47977    145 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    134   1.94019  4.61061  5.17838  4.67117  3.96915  4.65508  5.28276  1.37973  4.57265  2.60668  3.79310  4.80809  5.00205  4.81289  4.73487  4.03650  3.57041  1.05280  5.80976  4.59927    146 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    135   2.95269  4.69517  3.60665  1.97843  3.45446  3.85775  4.03090  3.11104  3.08550  1.51175  3.71657  3.54821  4.25024  3.42171  3.42726  3.14413  3.18521  2.92923  4.99169  2.16477    147 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    136   2.73695  4.65605  3.95869  3.70106  4.76353  3.44035  4.74373  4.12362  3.71195  3.84701  4.72350  3.83266  1.83108  4.03586  3.98938  2.92296  0.79061  3.61700  6.10688  4.92055    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    137   2.98616  1.77306  3.54257  2.96917  4.20397  3.77066  2.12431  3.65954  1.76469  3.27311  4.13902  3.40552  4.18321  3.14102  2.82770  3.07008  3.21991  3.37163  5.45841  4.17830    149 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    138   2.87318  2.27487  4.08101  3.51686  3.73262  3.86520  4.28384  2.71684  1.98443  2.72135  3.68760  3.80830  4.30540  3.67099  3.52284  3.18558  3.14569  1.41553  5.23503  4.02368    150 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    139   1.47784  5.66115  1.72234  1.61325  4.99518  3.55917  4.01510  4.49306  2.94403  3.99053  4.79675  3.03102  4.12373  3.15930  3.50625  3.04342  3.40107  4.05871  6.14898  4.67614    151 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    140   1.90208  4.30196  4.42388  3.85048  2.53064  3.96808  4.20458  2.66664  3.71202  2.43952  3.40720  3.98922  4.33968  3.90366  3.85104  3.27006  3.09799  1.78444  4.75310  1.94066    152 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    141   2.90716  5.18104  2.93680  1.74324  4.63204  3.55056  3.97551  4.06458  2.79684  3.63682  4.44671  3.14754  1.69442  3.12392  3.26513  2.91368  2.00011  3.66927  5.83669  4.46781    153 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    142   2.78359  4.49365  3.67376  3.10170  3.62714  3.76072  4.00455  2.07844  2.47123  1.90888  3.58652  3.50028  4.13823  2.73193  3.32251  3.01272  2.16843  2.73906  5.07658  3.84773    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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    143   2.78538  4.94129  3.12446  1.90128  4.30138  2.71211  3.90968  3.70356  2.74123  3.32793  4.14951  3.17742  4.01886  3.07350  3.19942  1.81320  3.05695  2.10287  5.57786  4.24807    155 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.01431  4.64966  5.37201  0.61958  0.77255  0.48576  0.95510
+    144   3.00331  5.31213  1.34717  2.61563  4.93207  1.88993  4.12688  4.41067  3.06726  3.95757  4.76779  3.14959  4.12417  3.28737  3.59771  2.99405  1.91587  3.94167  6.13257  4.71628    156 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.24219  4.64967  1.58216  0.61958  0.77255  0.48576  0.95510
+    145   2.90502  4.57765  3.77724  3.34069  3.46532  3.78667  1.98962  2.88032  3.15748  2.73793  3.75784  3.66796  4.25545  3.57022  3.42567  3.15372  3.18669  1.26808  5.01387  3.61579    157 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.01794  4.42541  5.14776  0.61958  0.77255  0.82155  0.57937
+    146   2.75147  4.74628  3.34357  2.80400  4.07335  3.57581  3.87957  3.30949  1.78780  3.06148  3.94193  3.25653  4.01680  3.07201  2.96883  2.85636  1.75071  2.41258  5.38823  4.11449    158 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.01794  4.42541  5.14776  0.61958  0.77255  0.82155  0.57937
+    147   3.00773  4.73948  3.43003  1.82450  3.89452  3.85717  4.23450  1.28531  3.14323  2.70935  3.80542  3.55715  4.30487  3.50591  3.49765  3.23918  3.26469  2.47035  5.46041  4.19035    159 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.01794  4.42541  5.14776  0.61958  0.77255  0.82155  0.57937
+    148   3.57591  5.69104  2.89034  0.43897  5.13067  3.74172  4.42582  4.71128  3.39211  4.24880  5.23832  3.41868  4.38352  3.65470  3.83330  3.52091  3.89687  4.34990  6.18698  4.96489    160 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.01794  4.42541  5.14776  0.61958  0.77255  0.82155  0.57937
+    149   2.88350  5.07456  2.83549  1.62789  4.53394  3.47506  3.97205  3.88890  2.80700  3.53770  4.39728  3.11273  4.03065  3.14364  3.24643  2.90638  1.35985  3.52987  5.77718  4.42810    161 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.01794  4.42541  5.14776  0.61958  0.77255  0.82155  0.57937
+    150   3.16212  4.85727  3.80335  3.36209  3.16774  3.96001  1.35846  3.22944  3.06257  1.59155  3.82989  3.70773  4.37953  3.54897  3.31681  3.33732  3.40874  3.10705  4.77246  3.24032    162 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.01794  4.42541  5.14776  0.61958  0.77255  0.82155  0.57937
+    151   2.94073  5.06198  3.33349  2.84187  4.57011  3.62118  3.89060  3.90975  1.20057  3.49273  4.35032  3.28330  4.09402  3.04189  2.67455  2.98263  1.83732  3.56058  5.65563  4.40287    163 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.01794  4.42541  5.14776  0.61958  0.77255  0.82155  0.57937
+    152   1.71060  5.15430  2.74244  1.20101  4.65798  3.45089  3.98759  4.03463  2.85903  3.66257  4.51252  3.07555  4.02822  3.15387  3.33026  2.91028  3.22047  3.64649  5.88103  4.50506    164 e - - -
+          2.68526  4.42272  2.77529  2.72949  3.46401  2.40536  3.72542  3.29401  2.67788  2.69262  4.24737  2.90394  2.73787  3.18194  2.89848  2.37934  2.77449  2.98523  4.58524  3.61550
+          0.55049  0.85960        *  1.51709  0.24763  0.00000        *
+//
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 ba4312a..ac807e1 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;
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 5182ad4..47b8aea 100644 (file)
@@ -36,6 +36,7 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.DBRefEntry;
 import jalview.datamodel.GeneLocus;
+import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.Mapping;
 import jalview.datamodel.PDBEntry;
@@ -48,7 +49,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.JvOptionPane;
@@ -90,6 +90,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
 {
@@ -151,7 +153,7 @@ public class Jalview2xmlTests extends Jalview2xmlBase
             DataSourceType.FILE);
     assertNotNull(af, "Didn't read input file " + inFile);
     af.loadJalviewDataFile(inAnnot, DataSourceType.FILE, null, null);
-    AlignViewport viewport = af.getViewport();
+    AlignViewportI viewport = af.getViewport();
     assertSame(viewport.getGlobalColourScheme().getClass(),
             TCoffeeColourScheme.class, "Didn't set T-coffee colourscheme");
     assertNotNull(
@@ -817,7 +819,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();
 
     /*
@@ -1062,6 +1064,59 @@ public class Jalview2xmlTests extends Jalview2xmlBase
   }
 
   /**
+   * 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());
+  }
+
+  /**
    * pre 2.11 - jalview 2.10 erroneously created new dataset entries for each
    * view (JAL-3171) this test ensures we can import and merge those views
    */
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 6b1fbd2..f488c55 100644 (file)
@@ -6,11 +6,13 @@ 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;
 import jalview.schemes.FeatureColour;
@@ -43,7 +45,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/FileUtilsTest.java b/test/jalview/util/FileUtilsTest.java
new file mode 100644 (file)
index 0000000..909d0c8
--- /dev/null
@@ -0,0 +1,73 @@
+package jalview.util;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+public class FileUtilsTest
+{
+  @Test(groups = "Functional")
+  public void testFindMatchingPaths() throws IOException
+  {
+    String expect1 = Paths.get("..", "jalview", "examples", "plantfdx.fa")
+            .toString();
+    String expect2 = Paths.get("../jalview/examples/plantfdx.features")
+            .toString();
+    String expect3 = Paths
+            .get("../jalview/examples/testdata/plantfdx.features")
+            .toString();
+
+    List<String> matches = FileUtils
+            .findMatchingPaths(Paths.get(".."),
+                    ".*[\\\\/]plant.*\\.f.*");
+    System.out.println(matches);
+    assertTrue(matches.contains(expect1));
+    assertTrue(matches.contains(expect2));
+    assertTrue(matches.contains(expect3));
+  }
+
+  @Test(groups = "External")
+  public void testWindowsPath() throws IOException
+  {
+    if (System.getProperty("os.name").startsWith("Windows"))
+    {
+      /*
+       * should pass provided Eclipse is installed
+       */
+      List<String> matches = FileUtils.findMatches("C:\\",
+              "Program Files*/eclips*/eclips?.exe");
+      assertFalse(matches.isEmpty());
+
+      /*
+       * should pass provided Chimera is installed
+       */
+      matches = FileUtils.findMatches("C:\\",
+              "Program Files*/Chimera*/bin/{chimera,chimera.exe}");
+      assertFalse(matches.isEmpty());
+    }
+  }
+
+  @Test(groups = "Functional")
+  public void testFindMatches() throws IOException
+  {
+    String expect1 = Paths.get("..", "jalview", "examples", "plantfdx.fa")
+            .toString();
+    String expect2 = Paths.get("../jalview/examples/plantfdx.features")
+            .toString();
+    String expect3 = Paths
+            .get("../jalview/examples/testdata/plantfdx.features")
+            .toString();
+  
+    List<String> matches = FileUtils
+            .findMatches("..", "jalview/ex*/plant*.f*");
+    System.out.println(matches);
+    assertTrue(matches.contains(expect1));
+    assertTrue(matches.contains(expect2));
+    assertFalse(matches.contains(expect3));
+  }
+}
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 86dcc39..493545a 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
index 084219a..9d805cc 100644 (file)
@@ -87,19 +87,6 @@ public class StringUtilsTest
   }
 
   @Test(groups = { "Functional" })
-  public void testGetLastToken()
-  {
-    assertNull(StringUtils.getLastToken(null, null));
-    assertNull(StringUtils.getLastToken(null, "/"));
-    assertEquals("a", StringUtils.getLastToken("a", null));
-
-    assertEquals("abc", StringUtils.getLastToken("abc", "/"));
-    assertEquals("c", StringUtils.getLastToken("abc", "b"));
-    assertEquals("file1.dat", StringUtils.getLastToken(
-            "file://localhost:8080/data/examples/file1.dat", "/"));
-  }
-
-  @Test(groups = { "Functional" })
   public void testSeparatorListToArray()
   {
     String[] result = StringUtils.separatorListToArray(
@@ -145,7 +132,7 @@ public class StringUtilsTest
   public void testListToDelimitedString()
   {
     assertEquals("", StringUtils.listToDelimitedString(null, ";"));
-    List<String> list = new ArrayList<String>();
+    List<String> list = new ArrayList<>();
     assertEquals("", StringUtils.listToDelimitedString(list, ";"));
     list.add("now");
     assertEquals("now", StringUtils.listToDelimitedString(list, ";"));
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
diff --git a/test/jalview/ws/ebi/HmmerJSONProcessTest.java b/test/jalview/ws/ebi/HmmerJSONProcessTest.java
new file mode 100644 (file)
index 0000000..bf68906
--- /dev/null
@@ -0,0 +1,122 @@
+package jalview.ws.ebi;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.io.DataSourceType;
+import jalview.io.FileFormat;
+import jalview.io.FileParse;
+import jalview.io.FormatAdapter;
+
+import java.io.File;
+
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class HmmerJSONProcessTest {
+  public static File alignmentFragFile = new File(
+          "examples/testdata/hmmer3/alignment_frag.fa.gz");
+
+  private AlignmentI getSearchResultFragmentAlignment() throws Exception
+  {
+    AlignmentI alf = new FormatAdapter().readFile(
+            alignmentFragFile.getAbsolutePath(), DataSourceType.FILE,
+            FileFormat.Fasta);
+
+    return alf;
+  }
+
+  public static File alignmentResultFile = new File(
+          "examples/testdata/hmmer3/alignment_res.fa.gz");
+
+  private AlignmentI getSearchResultAlignment() throws Exception
+  {
+    AlignmentI alf = new FormatAdapter().readFile(
+            alignmentResultFile.getAbsolutePath(), DataSourceType.FILE,
+            FileFormat.Fasta);
+
+    return alf;
+  }
+
+  public static String hitTestFile = "examples/testdata/hmmer3/hit_fragment.json.gz",
+          hmmerResultFile = "examples/testdata/hmmer3/hmmeresult.json.gz";
+
+
+  @Test(groups = { "Functional" })
+  public void parseHitTest() throws Exception
+  {
+
+    Assert.assertTrue(new File(hitTestFile).exists(),
+            "Can't find test data.\n"
+            + hitTestFile);
+    JSONParser jp = new JSONParser();
+    // read JSON in same way - via fileparse
+    Object hitfragment = jp.parse(new FileParse(hitTestFile,
+            DataSourceType.FILE).getReader());
+    Assert.assertTrue((hitfragment instanceof JSONObject),
+            "Didn't find a JSON object map in " + hitTestFile);
+    AlignmentI searchResult = getSearchResultFragmentAlignment();
+
+    Assert.assertTrue(searchResult != null && searchResult.getHeight() > 0,
+            "Didn't read search result alignment from " + alignmentFragFile);
+
+    HmmerJSONProcessor hjsp = new HmmerJSONProcessor(searchResult);
+    hjsp.addHit((JSONObject) hitfragment, 1);
+    // check that
+    // scores, posterior probabilities and stuff exist.
+  }
+
+  @Test(groups = { "Functional" })
+  public void parseJsonResultTest() throws Exception
+  {
+
+    Assert.assertTrue(new File(hmmerResultFile).exists(),
+            "Can't find test data.\n" + hmmerResultFile);
+
+    AlignmentI searchResult = getSearchResultAlignment();
+
+    Assert.assertTrue(searchResult != null && searchResult.getHeight() > 0,
+            "Didn't read search result alignment from " + alignmentFragFile);
+
+    HmmerJSONProcessor hjsp = new HmmerJSONProcessor(searchResult);
+    hjsp.parseFrom(new FileParse(hmmerResultFile, DataSourceType.FILE));
+    AlignmentAnnotation[] aa = searchResult.getSequenceAt(5)
+            .getAnnotation();
+    Assert.assertNotNull(aa);
+    Assert.assertEquals(aa.length, 3,
+            "didn't get expected set of annotation.\n");
+    // DPTSERWFHGHLSGKEAEKLLTeKGKHGSFLVRESQSHPGDFVLSVRTgddkgesndgKSKVTHVMIR-CQELKYDVGGGERFDSLTDLVEHYKKNPmvet
+    // LGTVLQLKQP
+    // 5789*****************9799***********************999998888888********.99**************************9999
+    // 899999*999
+    // AlignmentAnnotation
+    // 101 == 8
+    String seq = "tLGT";
+    SequenceI s5 = searchResult.getSequenceAt(5);
+    Assert.assertEquals(
+            s5.getSubSequence(s5.findIndex(225), s5.findIndex(229))
+                    .getSequenceAsString(),
+            seq);
+    int pos = s5.findIndex(226);
+    for (AlignmentAnnotation an : aa)
+    {
+      if (an.label.startsWith("Posterior"))
+      {
+        Assert.assertEquals(an.annotations[pos].value, 8f);
+
+      }
+    }
+    ;
+    // check that
+    // scores, posterior probabilities and stuff exist.
+  }
+  // Groovy test
+  // def al = Jalview.getAlignFrames()[0].getViewport().getAlignment()
+  // def jproc = new jalview.ws.ebi.HmmerJSONProcessor(al)
+  // jproc.parseFrom(new
+  // jalview.io.FileParse("examples/testdata/hmmer3/hmmeresult.json.gz","File"))
+  // jproc.updateView(Jalview.getAlignFrames()[0].getViewport())
+
+}
index 80b48c3..428f263 100644 (file)
@@ -28,6 +28,8 @@ 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.ArgumentI;
+import jalview.ws.params.ParamDatastoreI;
 
 import java.awt.BorderLayout;
 import java.awt.event.WindowAdapter;
@@ -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());
@@ -91,7 +93,7 @@ public class Jws2ParamView
     for (Jws2Instance service : disc.getServices())
     {
       if (serviceTests.size() == 0
-              || serviceTests.contains(service.serviceType.toLowerCase()))
+              || serviceTests.contains(service.getName().toLowerCase()))
       {
         List<Preset> prl = null;
         Preset pr = null;
@@ -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<ArgumentI>) 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 e8b6c2b..6698ed1 100644 (file)
@@ -82,10 +82,10 @@ public class DisorderAnnotExportImport
       Thread.sleep(100);
     }
 
-    iupreds = new ArrayList<Jws2Instance>();
+    iupreds = new ArrayList<>();
     for (Jws2Instance svc : disc.getServices())
     {
-      if (svc.getServiceTypeURI().toLowerCase().contains("iupredws"))
+      if (svc.getNameURI().toLowerCase().contains("iupredws"))
       {
         iupreds.add(svc);
       }
@@ -129,7 +129,7 @@ public class DisorderAnnotExportImport
     AlignmentI orig_alig = af.getViewport().getAlignment();
     // NOTE: Consensus annotation row cannot be exported and reimported
     // faithfully - so we remove them
-    List<AlignmentAnnotation> toremove = new ArrayList<AlignmentAnnotation>();
+    List<AlignmentAnnotation> toremove = new ArrayList<>();
     for (AlignmentAnnotation aa : orig_alig.getAlignmentAnnotation())
     {
       if (aa.autoCalculated)
index 889c003..3c83b71 100644 (file)
@@ -33,6 +33,7 @@ import jalview.io.FileFormat;
 import jalview.io.FormatAdapter;
 import jalview.io.StockholmFileTest;
 import jalview.project.Jalview2XML;
+import jalview.ws.jws2.JabaParamStore;
 import jalview.ws.jws2.Jws2Discoverer;
 import jalview.ws.jws2.RNAalifoldClient;
 import jalview.ws.jws2.SequenceAnnotationWSClient;
@@ -98,7 +99,7 @@ public class RNAStructExportImport
     for (Jws2Instance svc : disc.getServices())
     {
 
-      if (svc.getServiceTypeURI().toLowerCase().contains("rnaalifoldws"))
+      if (svc.getNameURI().toLowerCase().contains("rnaalifoldws"))
       {
         rnaalifoldws = svc;
       }
@@ -280,7 +281,8 @@ public class RNAStructExportImport
         opts.add(rg);
       }
     }
-    alifoldClient = new RNAalifoldClient(rnaalifoldws, af, null, opts);
+    alifoldClient = new RNAalifoldClient(rnaalifoldws, af, null,
+            JabaParamStore.getJwsArgsfromJaba(opts));
 
     af.getViewport().getCalcManager().startWorker(alifoldClient);
 
index c0aa2ee..66ce169 100644 (file)
@@ -26,6 +26,7 @@ import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.bin.Cache;
 import jalview.gui.JvOptionPane;
+import jalview.ws.api.UIinfo;
 import jalview.ws.jabaws.JalviewJabawsTestUtils;
 import jalview.ws.jws2.jabaws2.Jws2Instance;
 
@@ -61,7 +62,7 @@ public class ParameterUtilsTest
    * To limit tests to specify services, add them to this list; leave list empty
    * to test all
    */
-  private static List<String> serviceTests = new ArrayList<String>();
+  private static List<String> serviceTests = new ArrayList<>();
 
   private static Jws2Discoverer disc = null;
 
@@ -128,10 +129,10 @@ public class ParameterUtilsTest
    * @param service
    * @return
    */
-  public boolean isForTesting(Jws2Instance service)
+  public boolean isForTesting(UIinfo service)
   {
     return serviceTests.size() == 0
-            || serviceTests.contains(service.serviceType.toLowerCase());
+            || serviceTests.contains(service.getName().toLowerCase());
   }
 
   @Test(groups = { "Network" })
index 709f2c5..261c059 100644 (file)
@@ -25,6 +25,7 @@ import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.gui.AlignFrame;
 import jalview.gui.JvOptionPane;
+import jalview.ws.rest.clientdefs.ShmrRestClient;
 
 import java.util.Map;
 
@@ -52,13 +53,13 @@ public class ShmmrRSBSService
     assertTrue(
             "Test Rsd Exchange using using default Shmmr service failed.",
             testRsdExchange("Test using default Shmmr service",
-                    RestClient.makeShmmrRestClient().service));
+                    ShmrRestClient.makeShmmrRestClient().service));
   }
 
   @Test(groups = { "Functional" })
   public void testShmmrServiceDataprep() throws Exception
   {
-    RestClient _rc = RestClient.makeShmmrRestClient();
+    RestClient _rc = ShmrRestClient.makeShmmrRestClient();
     assertNotNull(_rc);
     AlignFrame alf = new jalview.io.FileLoader(false)
             .LoadFileWaitTillLoaded("examples/testdata/smad.fa",
@@ -127,6 +128,12 @@ public class ShmmrRSBSService
       if (!service.equals(newService))
       {
         System.err.println("Failed for service (" + desc + ").");
+        if (fromservicetostring.equals(newService.toString()))
+        {
+          System.err.println(
+                  "Description strings are equivalent: fault during RestServiceDescription.equals()");
+          return false;
+        }
         System.err.println("Original service and parsed service differ.");
         System.err.println("Original: " + fromservicetostring);
         System.err.println("Parsed  : " + newService.toString());
index 360a700..2cbfeb9 100755 (executable)
@@ -40,7 +40,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}" />