From: Charles Ofoegbu Date: Fri, 9 Jan 2015 15:11:09 +0000 (+0000) Subject: Merge branch 'features/JAL-1605_html-svg-export' into develop X-Git-Tag: Jalview_2_9~121 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=b5d61763044c1d72f06ce0e50da2171422a3774b;hp=81edd609f9841a84d5799d221277d45413a177cf;p=jalview.git Merge branch 'features/JAL-1605_html-svg-export' into develop --- diff --git a/.classpath b/.classpath index f87dd26..59772ae 100644 --- a/.classpath +++ b/.classpath @@ -45,15 +45,14 @@ + - - - - + + diff --git a/.gitignore b/.gitignore index c47ff62..0c12fb0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,6 @@ /.DS_Store .DS_Store /.com.apple.timemachine.supported +.gitattributes + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 884491a..f72955b 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,15 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.7 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 diff --git a/AUTHORS b/AUTHORS index 1bca12a..30db2a1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -14,6 +14,8 @@ In particular, check the resources/authors.props file ! Jim Procter Andrew Waterhouse +Mungo Carstairs +Tochukwu 'Charles' Ofoegbu Jan Engelhardt Lauren Lui Anne Menard diff --git a/THIRDPARTYLIBS b/THIRDPARTYLIBS index 386541e..ea44193 100644 --- a/THIRDPARTYLIBS +++ b/THIRDPARTYLIBS @@ -11,6 +11,7 @@ Licencing information for each library is given below: JGoogleAnalytics_0.3.jar APL 2.0 License - http://code.google.com/p/jgoogleanalytics/ Jmol-12.1.13.jar GPL/LGPLv2 http://sourceforge.net/projects/jmol/files/ +VARNAv3-91.jar GPL licenced software by Kévin Darty, Alain Denise and Yann Ponty. http://varna.lri.fr activation.jar apache-mime4j-0.6.jar axis.jar @@ -39,6 +40,7 @@ wsdl4j.jar xercesImpl.jar xml-apis.jar json_simple-1.1.jar : Apache 2.0 license : downloaded from https://code.google.com/p/json-simple/downloads/list (will move to 1.1.1 version when jalview is mavenised and osgi-ised) +jfreesvg-2.1.jar : GPL v3 licensed library from the JFree suite: http://www.jfree.org/jfreesvg/ Additional dependencies diff --git a/examples/example_biojs.html b/examples/example_biojs.html new file mode 100644 index 0000000..b6f7bec --- /dev/null +++ b/examples/example_biojs.html @@ -0,0 +1,9031 @@ + +
BioJS viewer
+ + + + + + + + Jalview Logo + +
+
+ + + + +
+
+ +
press "Run with JS"
+ + + + + + + + diff --git a/examples/uniref50.score_ascii b/examples/uniref50.score_ascii new file mode 100644 index 0000000..4a506d9 --- /dev/null +++ b/examples/uniref50.score_ascii @@ -0,0 +1,99 @@ +T-COFFEE, Version_8.99(Fri Feb 18 08:27:45 CET 2011 - Revision 596) +Cedric Notredame +CPU TIME:0 sec. +SCORE=94 +* + BAD AVG GOOD +* +FER_CAPAA : 99 +FER_CAPAN : 94 +FER1_SOLLC : 94 +Q93XJ9_SOLTU : 93 +FER1_PEA : 93 +Q7XA98_TRIPR : 92 +FER1_MESCR : 92 +FER1_SPIOL : 92 +FER3_RAPSA : 99 +FER1_ARATH : 93 +FER_BRANA : 99 +FER2_ARATH : 93 +Q93Z60_ARATH : 92 +FER1_MAIZE : 91 +O80429_MAIZE : 91 +cons : 94 + +FER_CAPAA ------------------------------------------------ +FER_CAPAN 99------333445778888876665554-23333345--6778765- +FER1_SOLLC 98------344556788888876665544-23333344--5677765- +Q93XJ9_SOLTU 98------344556788888876555554-23333344--5677765- +FER1_PEA 9964---1344556788888876655544-23333344--6778876- +Q7XA98_TRIPR 9964---1344566788888876665554-222222210056777650 +FER1_MESCR 9954--1124455677878765--22222122233345--5677776- +FER1_SPIOL 9965--111111--677777765444444233334445--6789876- +FER3_RAPSA ------------------------------------------------ +FER1_ARATH 9965----344556888888876665554233333344--6788776- +FER_BRANA ------------------------------------------------ +FER2_ARATH 9965----344556888888876665555233333345--6778876- +Q93Z60_ARATH 9965----344556888888876665555233333345--6778876- +FER1_MAIZE 99540001222334677777765555443--2222233--4567554- +O80429_MAIZE 9854---------23445555---11111111111111--1212222- +cons 996400012344557778887766544441222233340056777650 + + +FER_CAPAA -----------9999999999999999999999999999999999999 +FER_CAPAN 4--445678999999999999999999999999999999999999999 +FER1_SOLLC 4--445678999999999999999999999999999999999999999 +Q93XJ9_SOLTU 4--445678999999999999999999999999999999999999999 +FER1_PEA 533444568999999999999999999999999999999999999999 +Q7XA98_TRIPR 333434568999999999999999999999999999999999999999 +FER1_MESCR 4333-5678999999999999999999999999999999999999999 +FER1_SPIOL 422--2334599999999999999999999999999999999999999 +FER3_RAPSA -----------9999999999999999999999999999999999999 +FER1_ARATH 533446788999999999999999999999999999999999999999 +FER_BRANA -----------9999999999999999999999999999999999999 +FER2_ARATH 533546788999999999999999999999999999999999999999 +Q93Z60_ARATH 533546788999999999999999999999999999999999999999 +FER1_MAIZE 4222--567899999999999999999999999999999999999999 +O80429_MAIZE 222435678999999999999999999999999999999999999999 +cons 422445677899999999999999999999999999999999999999 + + +FER_CAPAA 999999999999999999999999999999999999999999999999 +FER_CAPAN 999999999999999999999999999999999999999999999999 +FER1_SOLLC 999999999999999999999999999999999999999999999999 +Q93XJ9_SOLTU 999999999999999999999999999999999999999999999999 +FER1_PEA 999999999999999999999999999999999999999999999999 +Q7XA98_TRIPR 999999999999999999999999999999999999999999999999 +FER1_MESCR 999999999999999999999999999999999999999999999999 +FER1_SPIOL 999999999999999999999999999999999999999999999999 +FER3_RAPSA 999999999999999999999999999999999999999999999999 +FER1_ARATH 999999999999999999999999999999999999999999999999 +FER_BRANA 999999999999999999999999999999999999999999999999 +FER2_ARATH 999999999999999999999999999999999999999999999999 +Q93Z60_ARATH 99999999999999999999999999999------------------- +FER1_MAIZE 999999999999999999999999999999999999999999999999 +O80429_MAIZE 999999999999999999999999999999999999999999999999 +cons 999999999999999999999999999999999999999999999999 + + +FER_CAPAA 999999998865- +FER_CAPAN 999999998865- +FER1_SOLLC 999999998865- +Q93XJ9_SOLTU 999999998865- +FER1_PEA 999999999865- +Q7XA98_TRIPR 999999998865- +FER1_MESCR 999999998865- +FER1_SPIOL 999999998865- +FER3_RAPSA 99999999874-- +FER1_ARATH 99999998874-- +FER_BRANA 99999999874-- +FER2_ARATH 99999998764-- +Q93Z60_ARATH ------------- +FER1_MAIZE 9999999998620 +O80429_MAIZE 99999999874-- +cons 9999999987550 + + + + + diff --git a/help/help.jhm b/help/help.jhm index b6b0063..af010a4 100755 --- a/help/help.jhm +++ b/help/help.jhm @@ -57,6 +57,7 @@ + @@ -122,10 +123,10 @@ + - diff --git a/help/helpTOC.xml b/help/helpTOC.xml index 1d45e7a..b67eb6f 100755 --- a/help/helpTOC.xml +++ b/help/helpTOC.xml @@ -1,153 +1,145 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - diff --git a/help/html/calculations/consensus.html b/help/html/calculations/consensus.html index bc42278..d5ce720 100644 --- a/help/html/calculations/consensus.html +++ b/help/html/calculations/consensus.html @@ -23,7 +23,7 @@

Alignment Consensus Annotation

The consensus displayed below the alignment is the percentage of the modal - residue per column. By default this calculation takes includes gaps in column. + residue per column. By default this calculation includes gaps in columns. You can choose to ignore gaps in the calculation by right clicking on the label "Consensus" to the left of the consensus bar chart.

If the modal value is shared by more than 1 residue, a "+" symbol @@ -38,7 +38,7 @@ clipboard. By clicking on the label you can also activate the sequence logo. It indicates the relative amount of residues per column which can be estimated by its size in the logo. The tooltip of a column gives the - exact numbers for all occuring residues. + exact numbers for all occurring residues.
If columns of the alignment are very diverse, then it can sometimes be difficult to see the sequence logo - in this case, right click on the annotation row label and select diff --git a/help/html/calculations/pca.html b/help/html/calculations/pca.html index 8d6f329..66dbabd 100755 --- a/help/html/calculations/pca.html +++ b/help/html/calculations/pca.html @@ -37,10 +37,10 @@ executing the calculation via a web service.

About PCA

Principal components analysis is a technique for examining the structure of complex data sets. The components are a set of dimensions -formed from the measured values in the data set, and the principle +formed from the measured values in the data set, and the principal component is the one with the greatest magnitude, or length. The sets of measurements that differ the most should lie at either end of this -principle axis, and the other axes correspond to less extreme patterns +principal axis, and the other axes correspond to less extreme patterns of variation in the data set.

diff --git a/help/html/colourSchemes/annotationColouring.html b/help/html/colourSchemes/annotationColouring.html index 75d9f55..5100c6b 100755 --- a/help/html/colourSchemes/annotationColouring.html +++ b/help/html/colourSchemes/annotationColouring.html @@ -58,6 +58,12 @@ symbols and graphs, this may be black by default, so your alignment will be coloured black. +

  • Secondary structure annotation colouring
    By + default, Jalview will employ the helix or sheet colours to shade + sequences and columns by available secondary structure annotation + tracks. In the case of RNA, each structure is processed to identify + distinct RNA helices and rendered in the same way as the RNA Helices shading scheme. Structure based sequence shading was added in Jalview 2.8.2
  • The colour scheme can display a colour gradient from a colour representing the minimum value in the selected annotation to a colour representing the maximum value in the selected annotation. Use the diff --git a/help/html/colourSchemes/pid.html b/help/html/colourSchemes/pid.html index 47b992a..d4e70fb 100755 --- a/help/html/colourSchemes/pid.html +++ b/help/html/colourSchemes/pid.html @@ -35,6 +35,7 @@ td { The PID option colours the residues (boxes and/or text) according to the percentage of the residues in each column that agree with the consensus sequence. Only the residues that agree with the consensus residue for each column are coloured.

    +
    @@ -49,5 +50,6 @@ td {
    > 80 %< 40%
    +
    diff --git a/help/html/features/annotation.html b/help/html/features/annotation.html index a036bd5..01d9f64 100755 --- a/help/html/features/annotation.html +++ b/help/html/features/annotation.html @@ -132,7 +132,7 @@ href="../features/jalarchive.html">Jalview Archives.

    Current Limitations

    As of version 2.5, the Jalview user interface does not support the -creation and editing quantitative annotation (histograms and line graphs), or +creation and editing of quantitative annotation (histograms and line graphs), or to create annotation associated with a specific sequence. It is also incapable of annotation grouping or changing the style of existing annotation (to change between line or bar charts, or to make multiple line graphs). These annotation capabilities are only possible by the import of an Annotation file.
    diff --git a/help/html/features/chimera.html b/help/html/features/chimera.html index 236701a..dbaad73 100644 --- a/help/html/features/chimera.html +++ b/help/html/features/chimera.html @@ -24,7 +24,7 @@

    The Chimera Viewer

    -

    Since Jalview 2.8.2, Chimera +

    Since Jalview 2.8.2, Chimera (http://www.cgl.ucsf.edu/chimera/) has been integrated into Jalview for interactively viewing structures opened by entries in the "Structure" submenu in the sequence id pop-up menu (if you can't see this, then you need to -

    Basic screen operations (see Chimera help for full details). +

    Basic screen operations (see Chimera help +(http://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/mouse.html) for full details). diff --git a/help/html/features/clarguments.html b/help/html/features/clarguments.html index 1cb1849..2a040fe 100644 --- a/help/html/features/clarguments.html +++ b/help/html/features/clarguments.html @@ -53,7 +53,7 @@ @@ -126,6 +126,13 @@ arguments have been processed + + + - +
    Action Set the colourscheme for the alignment. This can be any of the built-in colourschemes, a name of a predefined colourscheme - (defined in the jalview properties file), or an 'inline' colourscheme + (defined in the Jalview properties file), or an 'inline' colourscheme (see the applet's colour parameter for more information).
    +
    -jabaws URL
    +
    +
    Specify the URL of the preferred JABAWS server
    +
    -vdoc VAMSAS DOCUMENT FILE/URL
    @@ -196,7 +203,7 @@
    -svg FILE
    Create Support Vector Graphics file FILE from alignment.
    Create Scalable Vector Graphics file FILE from alignment.
    diff --git a/help/html/features/dassettings.html b/help/html/features/dassettings.html index 9676ed7..86162dc 100644 --- a/help/html/features/dassettings.html +++ b/help/html/features/dassettings.html @@ -45,7 +45,7 @@ more about these values.

    When the DAS Settings panel is first opened, and when the 'Refresh source' buton is pressed, a list of DAS sources is retrieved from the DAS registry URL (set by default to the DAS registration server at -http://das.sanger.ac.uk/registry/das1/sources/).

    +http://www.dasregistry.org/das/).

    Adding your own DAS Sources

    You can add your own DAS source to the list by clicking the "Add Local Source" button. Enter the URL and nickname of your diff --git a/help/html/features/featuresFormat.html b/help/html/features/featuresFormat.html index 8665e66..32b4ccb 100755 --- a/help/html/features/featuresFormat.html +++ b/help/html/features/featuresFormat.html @@ -163,7 +163,7 @@ Specify the start and end for a feature to be 0 in order to attach it to the whole sequence. Non-positional features are shown in a tooltip when the mouse hovers over the sequence ID panel, and any embedded links can be -accessed from the popup menu. Scores
    +accessed from the popup menu.
    Scores
    Scores can be associated with sequence features, and used to sort sequences or shade the alignment (this was added in jalview 2.5). The score field is optional, and malformed scores will be diff --git a/help/html/features/featuresettings.html b/help/html/features/featuresettings.html index 63217ee..3830302 100755 --- a/help/html/features/featuresettings.html +++ b/help/html/features/featuresettings.html @@ -76,8 +76,8 @@ alignment based on the average score or total number of currently active features and groups on each sequence. To order the alignment using a specific feature type, use the sort by .. entries in the pop-up menu for that type.
    -Feature sorting and graduated feature colouring was introduced -in jalview 2.5

    +Feature sorting and graduated feature colouring were introduced +in Jalview 2.5

    Transparency and Feature Ordering

    It is important to realise that sequence features are often not @@ -85,7 +85,7 @@ distinct and often overlap (for example, a metal binding site feature may be attached to one position along a stretch of sequence marked with a secondary structure feature).

    The ordering of the sequence features in the dialog box list is -the order used by jalview for rendering sequence features. A feature at +the order used by Jalview for rendering sequence features. A feature at the bottom of the list is rendered below a feature higher up in the list.
    You can change the order of a feature by diff --git a/help/html/features/hiddenRegions.html b/help/html/features/hiddenRegions.html index 9b85cf9..63920f5 100644 --- a/help/html/features/hiddenRegions.html +++ b/help/html/features/hiddenRegions.html @@ -41,7 +41,7 @@ web service alignments performed on visible sequences.

    A more advanced hide involves a right-mouse click on a sequence, then selecting "SequenceID -> Represent Group with SequenceId". Using this method of hiding sequences, any edits -performed on the visible group representative will be propogated to all +performed on the visible group representative will be propagated to all the sequences in that group.
    The hidden representative sequences will not be used in any calculations or web service alignments (nb. this may change in the future). diff --git a/help/html/features/multipleViews.html b/help/html/features/multipleViews.html index 209aba4..b1ccf4b 100644 --- a/help/html/features/multipleViews.html +++ b/help/html/features/multipleViews.html @@ -24,10 +24,10 @@

    Multiple Alignment Views

    -

    Multiple alignment views allows the same alignment to be viewed +

    Multiple alignment views allow the same alignment to be viewed independently in many different ways simultaneously. Each view is an independent visualization of the same alignment, so each may have a -different ordering, colouring, row and column hiding and seuqence +different ordering, colouring, row and column hiding and sequence feature and annotation display setting, but alignment, feature and annotation edits are common to all, since this affects the underlying data.

    diff --git a/help/html/features/seqfetch.html b/help/html/features/seqfetch.html index 6f4363b..5f0744d 100755 --- a/help/html/features/seqfetch.html +++ b/help/html/features/seqfetch.html @@ -25,7 +25,7 @@

    Sequence Fetcher

    Jalview can retrieve sequences from certain databases using either the -WSDBFetch service provided by the European Bioinformatics Institute, and, since Jalview 2.4, DAS servers capable of the sequence command (configured in DAS settings).

    +WSDBFetch service provided by the European Bioinformatics Institute, or, since Jalview 2.4, DAS servers capable of the sequence command (configured in DAS settings).

    The Jalview Sequence Fetcher Dialog Box

    The Sequence Fetcher dialog box can be opened via the "File" diff --git a/help/html/features/varna.html b/help/html/features/varna.html index ffc582b..290135c 100644 --- a/help/html/features/varna.html +++ b/help/html/features/varna.html @@ -30,7 +30,7 @@ selecting the "Structure→View Structure:" option in the sequence id pop-up menu (if you can't see this, then no RNA structure is associated with your -sequence or alignment. In the pop-up menu all structures that +sequence or alignment). In the pop-up menu all structures that are associated with this sequence and all sequences that are associated with the alignment are available. @@ -52,7 +52,7 @@ associated with the alignment are available. Individual structures: this is a structure associated with the individual sequence and therefore not related to the alignment

  • - +

    Controls

    • Rotate view - Left Click and drag
    • diff --git a/help/html/features/viewingpdbs.html b/help/html/features/viewingpdbs.html index 75a5c9c..99f17fe 100755 --- a/help/html/features/viewingpdbs.html +++ b/help/html/features/viewingpdbs.html @@ -31,8 +31,7 @@

      The Jmol viewer has been included since Jalview - 2.3. Jalview 2.8.2 included support for - Chimera, provided it is + 2.3. Jalview 2.8.2 included support for Chimera, provided it is installed and can be launched by Jalview. The default viewer can be configured in the Structure tab in the diff --git a/help/html/index.html b/help/html/index.html index 3a45fc8..11b6f2a 100755 --- a/help/html/index.html +++ b/help/html/index.html @@ -48,5 +48,32 @@

      Waterhouse, A.M., Procter, J.B., Martin, D.M.A, Clamp, M., Barton, G.J (2009),
      "Jalview version 2: A Multiple Sequence Alignment and Analysis Workbench,"
      Bioinformatics 25 (9) 1189-1191 doi: 10.1093/bioinformatics/btp033

      +

      The Jalview Authors
      + The following people have contributed to Jalview's development: +

        +
      • Jalview 1 +
        • Michele Clamp
        • +
        • James Cuff
        • +
        • Steve Searle
        • +
        • David Martin
        • +
        • Geoff Barton
        • +
        +
      • Jalview 2
          +
        • Jim Procter
        • +
        • Andrew Waterhouse
        • +
        • Mungo Carstairs
        • +
        • Tochukwu 'Charles' Ofoegbu
        • +
        • Jan Engelhardt
        • +
        • Lauren Lui
        • +
        • Anne Menard
        • +
        • Natasha Sherstnev
        • +
        • Daniel Barton
        • +
        • David Roldan-Martinez
        • +
        • David Martin
        • +
        • Geoff Barton
        • +
        +
      • +
      +

      diff --git a/help/html/io/export.html b/help/html/io/export.html index 6d121b8..518729b 100755 --- a/help/html/io/export.html +++ b/help/html/io/export.html @@ -35,7 +35,7 @@ diagrams and powerpoint presentations
    • EPS - an Encapsulated Postscript Document
      For high quality diagrams and publications. -
    • SVG - a Support Vector Graphics document
      For high quality +
    • SVG - a Scalable Vector Graphics document
      For high quality diagrams in publications and on the web.
    @@ -48,7 +48,7 @@ diagrams in publications and on the web. want an exact image of the alignment as displayed in Jalview. This is useful if a 3rd Party EPS viewer does not have the same Font which the EPS file was created with. -
  • When importing an EPS into to a Microsoft office document, a snapshot image of the +
  • When importing an EPS file into a Microsoft office document, a snapshot image of the file will be displayed which often looks blurred. Right-click the image and choose "Edit image." to convert it to word drawing objects which give a truer WYSIWIG representation. diff --git a/help/html/io/fileformats.html b/help/html/io/fileformats.html index 7bfc435..6017d4b 100755 --- a/help/html/io/fileformats.html +++ b/help/html/io/fileformats.html @@ -31,7 +31,7 @@ td { -

    Alignment Fileformats +

    Alignment File Formats

    Jalview understands a wide range of sequence alignment formats. In order to determine which format has been used for an alignment, jalview tries to detect some text or formatting unique to one of the formats: @@ -71,6 +71,11 @@ THISISASEQUENCE
    # STOCKHOLM VersionNumber
    ...
    // .stk, .sto + +Phylip +Line starts with two numbers separated by white space
    +...
    // +.phy

    The file extensions are used to associate jalview alignment icons diff --git a/help/html/jalviewjnlp.html b/help/html/jalviewjnlp.html deleted file mode 100755 index 8f32a2b..0000000 --- a/help/html/jalviewjnlp.html +++ /dev/null @@ -1,81 +0,0 @@ - - - -Jalview local Jnlp File - - -

    Jalview local Jnlp File

    -
    -<jnlp spec="1.0+" codebase="http://www.jalview.org/webstart/">
    -  <information>
    -    <title>Jalview</title>
    -    <vendor>The Barton Group</vendor>
    -    <homepage href="http://www.jalview.org"/>
    -    <description>Jalview Multiple Alignment Editor</description>
    -    <description kind="short">Jalview</description>
    -    <icon href="http://www.jalview.org/webstart/logo_big.gif" kind="default"/>
    -    <association extensions="fa" mime-type="application-x/ext-file"/>
    -    <association extensions="fasta" mime-type="application-x/ext-file"/>
    -    <association extensions="fastq" mime-type="application-x/ext-file"/>
    -    <association extensions="blc" mime-type="application-x/ext-file"/>
    -    <association extensions="msf" mime-type="application-x/ext-file"/>
    -    <association extensions="pfam" mime-type="application-x/ext-file"/>
    -    <association extensions="aln" mime-type="application-x/ext-file"/>
    -    <association extensions="pir" mime-type="application-x/ext-file"/>
    -    <association extensions="stk" mime-type="application-x/ext-file"/>
    -    <offline-allowed/>
    -  </information>
    -  <security>
    -    <all-permissions/>
    -  </security>
    -  <resources>
    -  <!-- the additional memory parameters are here -->
    -  <j2se version="1.5+" initial-heap-size="500M" max-heap-size="1000M"/>
    -		<jar href="jalview.jar"/>
    -		<jar href="JGoogleAnalytics-0.2.1-SNAPSHOT.jar"/>
    -		<jar href="Jmol-12.1.13.jar"/>
    -		<jar href="activation.jar"/>
    -		<jar href="axis.jar"/>
    -		<jar href="castor-1.1-cycle-xml.jar"/>
    -		<jar href="commons-discovery.jar"/>
    -		<jar href="commons-logging.jar"/>
    -		<jar href="jaxrpc.jar"/>
    -		<jar href="jhall.jar"/>
    -		<jar href="log4j-1.2.8.jar"/>
    -		<jar href="mail.jar"/>
    -		<jar href="min-jaba-client.jar"/>
    -		<jar href="regex.jar"/>
    -		<jar href="saaj.jar"/>
    -		<jar href="vamsas-client.jar"/>
    -		<jar href="wsdl4j.jar"/>
    -		<jar href="xercesImpl.jar"/>
    -		<jar href="xml-apis.jar"/>
    -		<property name="jalview.version" value="2.6.1"/>
    -  </resources>
    -  <application-desc main-class="jalview.bin.Jalview"/>
    -</jnlp>
    -
    -
    If -you have problems, send an email to jalview-discuss
    - - diff --git a/help/html/memory.html b/help/html/memory.html index 3ef4d77..1cb9596 100755 --- a/help/html/memory.html +++ b/help/html/memory.html @@ -45,24 +45,33 @@ The way you increase the memory settings for the JVM depends on which installation of Jalview you use:

      -
    • Web Start Version -

      JavaWS sets the JVM parameters through special tags in the JNLP file. You'll - need to make your own jnlp file and add the following parameter into the - <resources> element. -

      -<j2se version="1.5+" initial-heap-size="500M" max-heap-size="1000M"/>
      -
      - Save the jnlp file somewhere and then - if you start Jalview through your - web browser, point your browser at the file's url, othewise simply run javaws - with the file location as its argument. The file's url is something like :
      -
      +		
    • Web Start Version +

      + JavaWS sets the JVM parameters through special tags in the JNLP + file. You can obtain a JNLP file with modified memory settings from + our service with the following link (replace 2G with desired memory + in G or M):
      http://www.jalview.org/services/launchApp?jvm-max-heap=2G +

      +

      + Alternatively, if you want to create your own JNLP file then please + download the latest JNLP file from http://www.jalview.org/webstart/jalview.jnlp + and modify the max-heap-size parameter for the j2se tag in the + <resources> element. e.g. +

      +<j2se version="1.7+" initial-heap-size="500M" max-heap-size="1000M"/>
      +
      In both cases, you should save your new jnlp file somewhere and + then either point your web browser at the file's url, launch it from + your file browser, or from a terminal window run javaws (located in + your Java installation's bin directory) with the file location as its + argument. The file's url is something like :
       file://<full path to file>
      -
      - If jalview doesn't start up, see below. You'll have - to edit the above settings in the JNLP file using a text editor, save it, - and try starting Jalview with it once more. -

    • -
    • Install Anywhere version +
    • If jalview doesn't start up, see below. + You'll have to edit the above settings in the JNLP file using a text + editor, save it, and try starting Jalview with it once more. +

    • +
    • Install Anywhere version

      You need to change the InstallAnywhere configuration settings for the application. These are found in different places depending upon which operating system you have : diff --git a/help/html/menus/alignmentMenu.html b/help/html/menus/alignmentMenu.html index f67faa9..95dcad8 100755 --- a/help/html/menus/alignmentMenu.html +++ b/help/html/menus/alignmentMenu.html @@ -62,18 +62,16 @@ Select the format of the text by selecting one of the following menu items.

        -
      • FASTA -
      • -
      • MSF -
      • -
      • CLUSTAL -
      • -
      • BLC -
      • -
      • PIR -
      • -
      • PFAM -
      • +
      • FASTA
      • +
      • MSF
      • +
      • CLUSTAL
      • +
      • BLC
      • +
      • PIR
      • +
      • PFAM
      • +
      • PileUp
      • +
      • AMSA
      • +
      • STH
      • +
      • Phylip
    • Print (Control P)
      Jalview will print the alignment using the current fonts and colours of @@ -203,9 +201,9 @@ the last redundancy deletion.
    • Pad Gaps
      When selected, - the alignment will be kept at minimal width (so there no empty + the alignment will be kept at minimal width (so there are no empty columns before or after the first or last aligned residue) and all - sequences will be padded with gap characters to the before and + sequences will be padded with gap characters before and after their terminating residues.
      This switch is useful when making a tree using unaligned sequences and when working with alignment analysis programs which require 'properly aligned diff --git a/help/html/menus/alwedit.html b/help/html/menus/alwedit.html index e44f3ac..67b3d2e 100755 --- a/help/html/menus/alwedit.html +++ b/help/html/menus/alwedit.html @@ -91,8 +91,8 @@ undo the last redundancy deletion.
    • Pad Gaps
      When selected, the alignment will be kept at minimal width (so - there no empty columns before or after the first or last aligned - residue) and all sequences will be padded with gap characters to the + there are no empty columns before or after the first or last aligned + residue) and all sequences will be padded with gap characters before and after their terminating residues.
      This switch is useful when making a tree using unaligned sequences and when working with alignment analysis programs which require 'properly diff --git a/help/html/menus/alwfile.html b/help/html/menus/alwfile.html index 7cd096c..bf459e3 100755 --- a/help/html/menus/alwfile.html +++ b/help/html/menus/alwfile.html @@ -61,6 +61,10 @@
    • BLC
    • PIR
    • PFAM
    • +
    • PileUp
    • +
    • AMSA
    • +
    • STH
    • +
    • Phylip
  • Page Setup ...
    @@ -89,7 +93,7 @@
    Create a Portable Network Graphics file from your alignment.
  • SVG
    -
    Create a Support Vector Graphics file from your alignment for embedding in web pages.
  • + Create a Scalable Vector Graphics file from your alignment for embedding in web pages.
  • Export Features
    diff --git a/help/html/na/index.html b/help/html/na/index.html index f3c4a56..844b6b7 100644 --- a/help/html/na/index.html +++ b/help/html/na/index.html @@ -67,7 +67,7 @@ td { as LocaRNA output consensus RNA secondary structure lines in the line normally reserved for the Clustal consensus line in a clustal file.
  • - +
  • RNAML Jalview can import RNAML files containing sequences and extended secondary structure annotation derived from RNA 3D structure
  • RNA Secondary Structure Visualization and Analysis
    @@ -85,6 +85,10 @@ td { Visualization in VARNA - allows linked viewing of the consensus or an individual sequence's structure +

    Pseudo-knots
    + Jalview 2.8.2 introduced limited support for working with structures including pseudoknots. Where possible, extended WUSS symbols (e.g. different types of parentheses, or upper and lower case letters) are preserved when parsing RNA structure annotation and will be shaded differently when displayed in the structure.
    + Extended WUSS annotation is also employed to distinguish different base pair interactions obtained from RNAML files.

    +

    Limitations when working with RNA in Jalview
    Currently, Jalview is not able to export RNA secondary structure annotation in any format other than Jalview annotation
    diff --git a/help/html/privacy.html b/help/html/privacy.html index be5cf56..e19122c 100644 --- a/help/html/privacy.html +++ b/help/html/privacy.html @@ -25,7 +25,7 @@

    Privacy for Jalview Users

    The Jalview Desktop application which is available from the -www.jalview.org site does not contain code designed collect personal or +www.jalview.org site does not contain code designed to collect personal or private information without your consent. However, we do collect usage statistics to work out who is using Jalview, so we can apply for funding to support Jalview development, and make it better for our users.

    @@ -51,7 +51,7 @@ These are described below:


  • Google Analytics
    - Since jalview 2.4.0b2, the Jalview Desktop records usage data with + Since Jalview 2.4.0b2, the Jalview Desktop records usage data with Google Analytics via the JGoogleAnalytics class.
    @@ -68,7 +68,7 @@ program shouldn't try to contact any of the web servers mentioned above href="features/commandline.html">command line options to disable the questionnaire and usage statistics check. Finally, the Connections Tab of the -jalview preferences contains options for controlling the submission of +Jalview preferences contains options for controlling the submission of usage statistics.

    Other Web Clients in Jalview
    The Jalview desktop is intended to make it easier to interact with diff --git a/help/html/releases.html b/help/html/releases.html index 8913a32..92a39cb 100755 --- a/help/html/releases.html +++ b/help/html/releases.html @@ -25,41 +25,187 @@

    Release History

    - - - - - + + + + + - +
  • Output in Stockholm format
  • +
  • Internationalisation: improved Spanish (es) translation
  • +
  • Structure viewer preferences tab
  • +
  • Disorder and Secondary Structure annotation tracks shared + between alignments
  • +
  • UCSF Chimera launch and linked highlighting from Jalview
  • +
  • Show/hide all sequence associated annotation rows for all + or current selection
  • +
  • disorder and secondary structure predictions available as + dataset annotation
  • +
  • Per-sequence rna helices colouring
  • + + +
  • Sequence database accessions imported when fetching + alignments from Rfam
  • +
  • update VARNA version to 3.91
  • + +
  • New groovy scripts for exporting aligned positions, + conservation values, and calculating sum of pairs scores.
  • +
  • Command line argument to set default JABAWS server
  • +
  • include installation type in build properties and console + log output
  • +
  • Updated Jalview project format to preserve dataset annotation
  • + diff --git a/help/html/vamsas/index.html b/help/html/vamsas/index.html index b34289c..fcc9b0c 100644 --- a/help/html/vamsas/index.html +++ b/help/html/vamsas/index.html @@ -94,7 +94,7 @@ crashes or otherwise fails, the VAMSAS session it is connected to will whilst it is still connected to a session, that session can be recovered in a new Jalview instance using the Vamsas→"Existing session" sub menu.

    -A quick Demo +

    A quick Demo
    Jalview can talk to itself through VAMSAS. Simply start two copies of the application, create a new vamsas session in one, and connect to the diff --git a/help/html/webServices/RNAalifold.html b/help/html/webServices/RNAalifold.html index 55fe70c..6c3c6b5 100644 --- a/help/html/webServices/RNAalifold.html +++ b/help/html/webServices/RNAalifold.html @@ -62,7 +62,7 @@ Partition Function (-p)
    Calculate the Partition Function and base pairing probability matrix in addition to the mfe structure. A coarse representation of the pair probabilities in the - from of a pseudo bracket notation, as well as the centroid structure + form of a pseudo bracket notation, as well as the centroid structure derived from the pair probabilities are displayed. The most likely base pairings are stored in a separate file by RNAalifold and represented in Jalview by a bar graph annotation line labeled diff --git a/help/html/webServices/dbreffetcher.html b/help/html/webServices/dbreffetcher.html index ad42153..b02f940 100644 --- a/help/html/webServices/dbreffetcher.html +++ b/help/html/webServices/dbreffetcher.html @@ -49,7 +49,7 @@ reference, and any cross-references that its records contain.

    The Sequence Identification Process
    The method of accession id discovery is derived from the method which earlier Jalview versions used for Uniprot sequence feature retrieval, -and was originally restricted to the identifaction of valid Uniprot +and was originally restricted to the identification of valid Uniprot accessions.
    Essentially, Jalview will try to retrieve records from a subset of the databases accessible by the sequence diff --git a/help/html/whatsNew.html b/help/html/whatsNew.html index ae45aae..a5d5d4a 100755 --- a/help/html/whatsNew.html +++ b/help/html/whatsNew.html @@ -29,12 +29,80 @@

    Jalview 2.8.2 is the first release produced by our new core development team.
    It incorporates many minor improvements and - bug-fixes, and also includes new features for working with 3D - structure data, shading alignments by secondary structure and - generation of alignment figures as Scalable Vector Graphics.
    As - ever, the highlights are detailed below, and the full list is given in - the
    Jalview 2.8.2 Release - Notes. + bug-fixes, and new features for working with 3D structure data, + shading alignments by secondary structure and generation of alignment + figures as Scalable Vector Graphics.
    The majority of + improvements in this version of Jalview concern the desktop + application. As ever, the highlights are detailed below, + and the full list is given in the Jalview 2.8.2 Release Notes.

    +

    + Annotation visualisation
    The alignment window + includes a new Annotations menu which provides controls for + the layout and display of sequence, group and alignment associated + annotation rows. It also now includes the Autocalculated + Annotation submenu (formerly located in the View menu), which + includes settings for the calculation and display of sequence + consensus, logos, and amino acid conservation for the alignment and + subgroups. +

    +

    + Sequence associated annotation
    New controls + have also been added to the Sequence ID popup menu for the propagation + and display of sequence associated annotation such as secondary + structure assignments and disorder predictions. Annotation associated + with one or a group of sequence already shown on the alignment may be + shown or hidden, and any available annotation from 3D structure or + calculations performed in other Jalview windows can be copied to the + alignment + via the Add Reference Annotation option.
    + The Colour by annotation function has also been + improved, allowing secondary structure annotation to be used to shade + sequences and alignment columns. Protein sequences can be coloured + according to the presence of a helix or sheet at each position, and + RNA sequences can be shaded according to each structure's stem/helix + pattern - which enables different RNA folding topologies to be quickly + identified. +

    +

    + 3D Structural data analysis and display
    + Jalview now employs Jmol's PDB data API to retrieve secondary + structure assignments made by the DSSP algorithm. It can also employ + web services to obtain secondary structure assignments from RNA + structures. These assignments are shown as sequence associated + annotation for sequences which have cross-references to the PDB, or + have had PDB files associated with them via the Structures + submenu of the sequence ID popup menu. The extraction and display of + secondary structure and B-factor column annotation is controlled via + a new Structure tab in the Jalview Desktop's + Preferences dialog box. +

    +

    + Interoperation with UCSF Chimera
    The desktop + application can now be configured to employ UCSF Chimera for the + display of 3D structure data. UCSF Chimera is a python-based + high-performance molecular graphics and animation system developed by + the Resource for Biocomputing, Visualisation, and Informatics at the + University of California.
    Jalview employs the 'StructureViz' + communication mechanism developed for Cytoscape by Morris et al. + (http://www.ncbi.nlm.nih.gov/pubmed/17623706) in 2007. This mechanism + allows Jalview to send commands to Chimera, enabling structures to be + superimposed and shaded according to associated multiple aligmment + views.
    Support for Chimera in Jalview 2.8.2 is experimental, and we + would appreciate feedback ! Please send your comments to + jalview-discuss@jalview.org, and keep up to date with this feature's + development via http://issues.jalview.org/browse/JAL-1333. +

    +

    + Export of alignment figures as Scalable Vector + Graphics
    Scalable Vector Graphics (SVG) files are now widely + supported by web browsers and graphics design programs, and allow + high-quality graphics for interactive exploration and publication. + Jalview now supports the generation of SVGs interactively (via the + Export) menu, and from the command line for server-side figure + generation. +

    + diff --git a/lib/jsoup-1.8.1.jar b/lib/jsoup-1.8.1.jar new file mode 100644 index 0000000..ae717d4 Binary files /dev/null and b/lib/jsoup-1.8.1.jar differ diff --git a/resources/authors.props b/resources/authors.props index e57ce3e..d41c2ca 100644 --- a/resources/authors.props +++ b/resources/authors.props @@ -1,4 +1,4 @@ YEAR=2014 -AUTHORS=J Procter, AM Waterhouse, J Engelhardt, LM Lui, A Menard, D Barton, N Sherstnev, D Roldan-Martinez, M Clamp, S Searle, G Barton -AUTHORFNAMES=Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, Anne Menard, Daniel Barton, Natasha Sherstnev, David Roldan-Martinez, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton +AUTHORS=J Procter, AM Waterhouse, M Carstairs, TC Ofoegbu, J Engelhardt, LM Lui, A Menard, D Barton, N Sherstnev, D Roldan-Martinez, M Clamp, S Searle, G Barton +AUTHORFNAMES=Jim Procter, Andrew Waterhouse, Mungo Carstairs, Tochukwu 'Charles' Ofoegbu, Jan Engelhardt, Lauren Lui, Anne Menard, Daniel Barton, Natasha Sherstnev, David Roldan-Martinez, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton \ No newline at end of file diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index cabee76..fce8470 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -251,6 +251,7 @@ label.structure_viewer = Default structure viewer label.chimera_path = Path to Chimera program label.chimera_path_tip = Jalview will first try any path entered here, else standard installation locations.
    Double-click to browse for file. label.invalid_chimera_path = Chimera path not found or not executable +label.chimera_missing = Chimera structure viewer not found.
    Please enter the path to Chimera (if installed),
    or download and install UCSF Chimera. label.min_colour = Minimum Colour label.max_colour = Maximum Colour label.use_original_colours = Use Original Colours @@ -438,8 +439,8 @@ label.redundancy_threshold_selection = Redundancy threshold selection label.user_defined_colours = User defined colours label.jalviewLite_release = JalviewLite - Release {0} label.jaview_build_date = Build date: {0} -label.jalview_authors_1 = Authors: : Jim Procter, Andrew Waterhouse, Lauren Lui, Jan Engelhardt, Natasha Sherstnev, -label.jalview_authors_2 = Daniel Barton, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton. +label.jalview_authors_1 = Authors: Jim Procter, Andrew Waterhouse, Mungo Carstairs, Tochukwu Ofoegbu, Lauren Lui, Jan Engelhardt, +label.jalview_authors_2 = Natasha Sherstnev, Daniel Barton, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton. label.jalview_dev_managers = Development managed by The Barton Group, University of Dundee, Scotland, UK. label.jalview_distribution_lists = For help, see the FAQ at www.jalview.org and/or join the jalview-discuss@jalview.org mailing list label.jalview_please_cite = If you use Jalview, please cite: @@ -1094,6 +1095,7 @@ warn.job_cannot_be_cancelled_close_window = This job cannot be cancelled.\nJust warn.service_not_supported = Service not supported! warn.input_is_too_big = Input is too big! warn.invalid_job_param_set = Invalid job parameter set! +warn.oneseq_msainput_selection = The current selection only contains a single sequence. Do you want to submit all sequences for alignment instead ? info.job_couldnt_be_run_server_doesnt_support_program = Job could not be run because the server doesn't support this program.\n{0} info.job_couldnt_be_run_exceeded_hard_limit = Job could not be run because it exceeded a hard limit on the server.\n{0} info.job_couldnt_be_run_incorrect_param_setting = Job could not be run because some of the parameter settings are not supported by the server.\n{0}\nPlease check to make sure you have used the correct parameter set for this service\!\n @@ -1103,6 +1105,8 @@ info.invalid_jnet_job_result_data ={0}\n{1}\nInvalid JNet job result data\!\n{2} info.failed_to_submit_sequences_for_alignment = Failed to submit sequences for alignment.\nIt is most likely that there is a problem with the server.\nJust close the window\n info.alignment_object_method_notes = \nAlignment Object Method Notes\n info.server_exception = \n{0} Server exception\!\n{1} +info.invalid_msa_input_mininfo = Need at least two sequences with at least 3 residues each, with no hidden regions between them. +info.invalid_msa_notenough = Not enough sequence data to align status.processing_commandline_args = Processing commandline arguments... status.das_features_being_retrived = DAS features being retrieved... status.searching_for_sequences_from = Searching for sequences from {0} diff --git a/resources/lang/Messages_es.properties b/resources/lang/Messages_es.properties index dc403d0..241fff2 100644 --- a/resources/lang/Messages_es.properties +++ b/resources/lang/Messages_es.properties @@ -418,8 +418,8 @@ label.redundancy_threshold_selection = Selecci label.user_defined_colours = Colores definidos del usuario label.jalviewLite_release = JalviewLite - versión {0} label.jaview_build_date = Fecha de creación: {0} -label.jalview_authors_1 = Authors: Jim Procter, Andrew Waterhouse, Jan Engelhardt, Lauren Lui, -label.jalview_authors_2 = Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton. +label.jalview_authors_1 = Authors: Jim Procter, Andrew Waterhouse, Mungo Carstairs, Tochukwu Ofoegbu, Lauren Lui, Jan Engelhardt, +label.jalview_authors_2 = Natasha Sherstnev, Daniel Barton, Michele Clamp, James Cuff, Steve Searle, David Martin & Geoff Barton. label.jalview_dev_managers = Desarrollo gestionado por The Barton Group, University of Dundee, Scotland, UK. label.jalview_distribution_lists = Para ayuda, ver el FAQ at www.jalview.org y/o adjuntar la lista de envío jalview-discuss@jalview.org label.jalview_please_cite = Si usa Jalview incluya la siguiente cita, por favor: diff --git a/resources/templates/BioJSTemplate.txt b/resources/templates/BioJSTemplate.txt new file mode 100644 index 0000000..bf780bb --- /dev/null +++ b/resources/templates/BioJSTemplate.txt @@ -0,0 +1,9032 @@ + +
    BioJS viewer
    + + + + + + + + Jalview Logo + +
    +
    + + + + +
    +
    + +
    press "Run with JS"
    + + + + + + + + \ No newline at end of file diff --git a/src/MCview/AppletPDBCanvas.java b/src/MCview/AppletPDBCanvas.java index a1bb272..9b0412a 100644 --- a/src/MCview/AppletPDBCanvas.java +++ b/src/MCview/AppletPDBCanvas.java @@ -550,7 +550,7 @@ public class AppletPDBCanvas extends Panel implements MouseListener, StructureMapping[] mapping = ssm.getMapping(pdbentry.getFile()); boolean showFeatures = false; - if (ap.av.getShowSequenceFeatures()) + if (ap.av.isShowSequenceFeatures()) { if (fr == null) { diff --git a/src/MCview/PDBCanvas.java b/src/MCview/PDBCanvas.java index dc0f718..4fd7a35 100644 --- a/src/MCview/PDBCanvas.java +++ b/src/MCview/PDBCanvas.java @@ -110,7 +110,7 @@ public class PDBCanvas extends JPanel implements MouseListener, boolean seqColoursReady = false; - jalview.gui.FeatureRenderer fr; + jalview.renderer.seqfeatures.FeatureRenderer fr; Color backgroundColour = Color.black; @@ -520,7 +520,7 @@ public class PDBCanvas extends JPanel implements MouseListener, StructureMapping[] mapping = ssm.getMapping(pdbentry.getFile()); boolean showFeatures = false; - if (ap.av.getShowSequenceFeatures()) + if (ap.av.isShowSequenceFeatures()) { if (fr == null) { diff --git a/src/MCview/PDBChain.java b/src/MCview/PDBChain.java index 408108b..49d7d4a 100755 --- a/src/MCview/PDBChain.java +++ b/src/MCview/PDBChain.java @@ -522,6 +522,7 @@ public class PDBChain ana.getCalcId(), ana.label); if (transfer == null || transfer.size() == 0) { + ana = new AlignmentAnnotation(ana); ana.liftOver(sequence, shadowMap); ana.liftOver(dsq, sqmpping); dsq.addAlignmentAnnotation(ana); @@ -534,24 +535,25 @@ public class PDBChain } else { - if (sequence != null && sequence.getAnnotation() != null) - { - for (AlignmentAnnotation ana : sequence.getAnnotation()) + if (sequence != null && sequence.getAnnotation() != null) { - List transfer = sq.getAlignmentAnnotations( - ana.getCalcId(), ana.label); - if (transfer == null || transfer.size() == 0) - { - ana.liftOver(dsq, sqmpping); - // mapping.transfer(ana); - } - else + for (AlignmentAnnotation ana : sequence.getAnnotation()) { - continue; + List transfer = sq + .getAlignmentAnnotations(ana.getCalcId(), ana.label); + if (transfer == null || transfer.size() == 0) + { + ana = new AlignmentAnnotation(ana); + ana.liftOver(dsq, sqmpping); + // mapping.transfer(ana); + } + else + { + continue; + } } } } - } if (false) { // Useful for debugging mappings - adds annotation for mapped position diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java b/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java index a7440e7..b45404e 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/ChimeraManager.java @@ -1,14 +1,21 @@ package ext.edu.ucsf.rbvi.strucviz2; +import jalview.ws.HttpClientUtils; + import java.awt.Color; +import java.io.BufferedReader; import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,10 +27,19 @@ import ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads; */ public class ChimeraManager { + private static final boolean debug = false; + + /* + * true: use REST API (recommended), false: use stdout/stdin (deprecated) + */ + // TODO remove once definitely happy with using REST + private static final boolean USE_REST = true; + + private int chimeraRestPort; private Process chimera; - private ListenerThreads chimeraListenerThreads; + private ListenerThreads chimeraListenerThread; private Map currentModelsMap; @@ -36,7 +52,7 @@ public class ChimeraManager { this.structureManager = structureManager; chimera = null; - chimeraListenerThreads = null; + chimeraListenerThread = null; currentModelsMap = new HashMap(); } @@ -354,7 +370,15 @@ public class ChimeraManager { chimera = null; currentModelsMap.clear(); - chimeraListenerThreads = null; + if (USE_REST) + { + this.chimeraRestPort = 0; + } + else + { + chimeraListenerThread.requestStop(); + chimeraListenerThread = null; + } structureManager.clearOnChimeraExit(); } @@ -525,12 +549,13 @@ public class ChimeraManager List args = new ArrayList(); args.add(chimeraPath); args.add("--start"); - args.add("ReadStdin"); + args.add(USE_REST ? "RESTServer" : "ReadStdin"); ProcessBuilder pb = new ProcessBuilder(args); chimera = pb.start(); error = ""; workingPath = chimeraPath; - logger.info("Strarting " + chimeraPath); + logger.info("Starting " + chimeraPath + " with " + + (USE_REST ? "REST API" : "stdin/stdout")); break; } catch (Exception e) { @@ -541,10 +566,18 @@ public class ChimeraManager // If no error, then Chimera was launched successfully if (error.length() == 0) { - // Initialize the listener threads - chimeraListenerThreads = new ListenerThreads(chimera, - structureManager); - chimeraListenerThreads.start(); + if (USE_REST) + { + this.chimeraRestPort = getPortNumber(); + System.out.println("Chimera REST API on port " + chimeraRestPort); + } + else + { + // Initialize the listener threads + chimeraListenerThread = new ListenerThreads(chimera, + structureManager); + chimeraListenerThread.start(); + } // structureManager.initChimTable(); structureManager.setChimeraPathProperty(workingPath); // TODO: [Optional] Check Chimera version and show a warning if below 1.8 @@ -559,6 +592,42 @@ public class ChimeraManager } /** + * Read and return the port number returned in the reply to --start RESTServer + */ + private int getPortNumber() + { + int port = 0; + InputStream readChan = chimera.getInputStream(); + BufferedReader lineReader = new BufferedReader(new InputStreamReader( + readChan)); + String response = null; + try + { + // expect: REST server on host 127.0.0.1 port port_number + response = lineReader.readLine(); + String [] tokens = response.split(" "); + if (tokens.length == 7 && "port".equals(tokens[5])) { + port = Integer.parseInt(tokens[6]); + logger.info("Chimera REST service listening on port " + + chimeraRestPort); + } + } catch (Exception e) + { + logger.error("Failed to get REST port number from " + response + ": " + + e.getMessage()); + } finally + { + try + { + lineReader.close(); + } catch (IOException e2) + { + } + } + return port; + } + + /** * Determine the color that Chimera is using for this model. * * @param model @@ -683,7 +752,8 @@ public class ChimeraManager */ public List sendChimeraCommand(String command, boolean reply) { - if (!isChimeraLaunched()) + if (!isChimeraLaunched() || command == null + || "".equals(command.trim())) { return null; } @@ -699,38 +769,102 @@ public class ChimeraManager ; } busy = true; + long startTime = System.currentTimeMillis(); try { - chimeraListenerThreads.clearResponse(command); - String text = command.concat("\n"); - // System.out.println("send command to chimera: " + text); - try + if (USE_REST) { - // send the command - chimera.getOutputStream().write(text.getBytes()); - chimera.getOutputStream().flush(); - } catch (IOException e) - { - // logger.info("Unable to execute command: " + text); - // logger.info("Exiting..."); - logger.warn("Unable to execute command: " + text); - logger.warn("Exiting..."); - clearOnChimeraExit(); - // busy = false; - return null; + return sendRestCommand(command); } - if (!reply) + else { - // busy = false; - return null; + return sendStdinCommand(command, reply); } - List rsp = chimeraListenerThreads.getResponse(command); - // busy = false; - return rsp; } finally { busy = false; + if (debug) + { + System.out.println("Chimera command took " + + (System.currentTimeMillis() - startTime) + "ms: " + + command); + } + + } + } + + /** + * Sends the command to Chimera's REST API, and returns any response lines. + * + * @param command + * @return + */ + protected List sendRestCommand(String command) + { + // TODO start a separate thread to do this so we don't block? + String restUrl = "http://127.0.0.1:" + this.chimeraRestPort + "/run"; + List commands = new ArrayList(1); + commands.add(new BasicNameValuePair("command", command)); + + List reply = new ArrayList(); + BufferedReader response = null; + try { + response = HttpClientUtils.doHttpUrlPost(restUrl, + commands); + String line = ""; + while ((line = response.readLine()) != null) { + reply.add(line); + } + } catch (Exception e) + { + logger.error("REST call " + command + " failed: " + e.getMessage()); + } finally + { + if (response != null) + { + try + { + response.close(); + } catch (IOException e) + { + } + } + } + return reply; + } + + /** + * Send a command to stdin of Chimera process, and optionally read any + * responses. + * + * @param command + * @param readReply + * @return + */ + protected List sendStdinCommand(String command, boolean readReply) + { + chimeraListenerThread.clearResponse(command); + String text = command.concat("\n"); + try + { + // send the command + chimera.getOutputStream().write(text.getBytes()); + chimera.getOutputStream().flush(); + } catch (IOException e) + { + // logger.info("Unable to execute command: " + text); + // logger.info("Exiting..."); + logger.warn("Unable to execute command: " + text); + logger.warn("Exiting..."); + clearOnChimeraExit(); + return null; + } + if (!readReply) + { + return null; } + List rsp = chimeraListenerThread.getResponse(command); + return rsp; } public StructureManager getStructureManager() diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java b/src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java index 1208638..4797b37 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/StructureManager.java @@ -864,22 +864,24 @@ public class StructureManager StructureSettings defaultSettings = null; // TODO: [Optional] Change priority of Chimera paths - public List getChimeraPaths() + public static List getChimeraPaths() { List pathList = new ArrayList(); // if no network is available and the settings have been modified by the // user, check for a // path to chimera - if (defaultSettings != null) - { - String defaultPath = defaultSettings.getChimeraPath(); - if (defaultPath != null && !defaultPath.equals("")) - { - pathList.add(defaultPath); - return pathList; - } - } + // + // For Jalview, Preferences/Cache plays this role instead + // if (defaultSettings != null) + // { + // String defaultPath = defaultSettings.getChimeraPath(); + // if (defaultPath != null && !defaultPath.equals("")) + // { + // pathList.add(defaultPath); + // return pathList; + // } + // } /* * Jalview addition: check if path set in user preferences. @@ -887,7 +889,7 @@ public class StructureManager String userPath = Cache.getDefault(Preferences.CHIMERA_PATH, null); if (userPath != null) { - pathList.add(userPath); + pathList.add(0, userPath); } // Add default installation paths diff --git a/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java b/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java index 883d536..2b2ce48 100644 --- a/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java +++ b/src/ext/edu/ucsf/rbvi/strucviz2/port/ListenerThreads.java @@ -21,207 +21,282 @@ import ext.edu.ucsf.rbvi.strucviz2.StructureManager; /** * Reply listener thread */ -public class ListenerThreads extends Thread { - private InputStream readChan = null; - private BufferedReader lineReader = null; - private Process chimera = null; - private Map> replyLog = null; - private Logger logger; - private StructureManager structureManager = null; - - /** - * Create a new listener thread to read the responses from Chimera - * - * @param chimera - * a handle to the Chimera Process - * @param log - * a handle to a List to post the responses to - * @param chimeraObject - * a handle to the Chimera Object - */ - public ListenerThreads(Process chimera, StructureManager structureManager) { - this.chimera = chimera; - this.structureManager = structureManager; - replyLog = new HashMap>(); - // Get a line-oriented reader - readChan = chimera.getInputStream(); - lineReader = new BufferedReader(new InputStreamReader(readChan)); - logger = LoggerFactory.getLogger(ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads.class); - } - - /** - * Start the thread running - */ - public void run() { - // System.out.println("ReplyLogListener running"); - while (true) { - try { - chimeraRead(); - } catch (IOException e) { - logger.warn("UCSF Chimera has exited: " + e.getMessage()); - return; - } - } - } - - public List getResponse(String command) { - List reply; - // System.out.println("getResponse: "+command); +public class ListenerThreads extends Thread +{ + private BufferedReader lineReader = null; + + private Process chimera = null; + + private Map> replyLog = null; + + private Logger logger; + + private StructureManager structureManager = null; + + private boolean stopMe = false; + + /** + * Create a new listener thread to read the responses from Chimera + * + * @param chimera + * a handle to the Chimera Process + * @param structureManager + * a handle to the Chimera structure manager + */ + public ListenerThreads(Process chimera, StructureManager structureManager) + { + this.chimera = chimera; + this.structureManager = structureManager; + replyLog = new HashMap>(); + // Get a line-oriented reader + InputStream readChan = chimera.getInputStream(); + lineReader = new BufferedReader(new InputStreamReader(readChan)); + logger = LoggerFactory + .getLogger(ext.edu.ucsf.rbvi.strucviz2.port.ListenerThreads.class); + } + + /** + * Start the thread running + */ + public void run() + { + // System.out.println("ReplyLogListener running"); + while (!stopMe) + { + try + { + chimeraRead(); + } catch (IOException e) + { + logger.warn("UCSF Chimera has exited: " + e.getMessage()); + return; + } finally + { + if (lineReader != null) + { + try + { + lineReader.close(); + } catch (IOException e) + { + } + } + } + } + } + + public List getResponse(String command) + { + List reply; + // System.out.println("getResponse: "+command); // TODO do we need a maximum wait time before aborting? - while (!replyLog.containsKey(command)) { - try { - Thread.currentThread().sleep(100); - } catch (InterruptedException e) { - } - } - - synchronized (replyLog) { - reply = replyLog.get(command); - // System.out.println("getResponse ("+command+") = "+reply); - replyLog.remove(command); - } - return reply; - } - - public void clearResponse(String command) { - try { - Thread.currentThread().sleep(100); - } catch (InterruptedException e) { - } - if (replyLog.containsKey(command)) + while (!replyLog.containsKey(command)) + { + try + { + Thread.currentThread().sleep(100); + } catch (InterruptedException e) + { + } + } + + synchronized (replyLog) { + reply = replyLog.get(command); + // System.out.println("getResponse ("+command+") = "+reply); replyLog.remove(command); } - return; - } + return reply; + } - /** - * Read input from Chimera - * - * @return a List containing the replies from Chimera - */ - private void chimeraRead() throws IOException { - if (chimera == null) + public void clearResponse(String command) + { + try + { + Thread.currentThread().sleep(100); + } catch (InterruptedException e) + { + } + if (replyLog.containsKey(command)) + { + replyLog.remove(command); + } + return; + } + + /** + * Read input from Chimera + * + * @return a List containing the replies from Chimera + */ + private void chimeraRead() throws IOException + { + if (chimera == null) { return; } - String line = null; - while ((line = lineReader.readLine()) != null) { - // System.out.println("From Chimera-->" + line); - if (line.startsWith("CMD")) { - chimeraCommandRead(line.substring(4)); - } else if (line.startsWith("ModelChanged: ")) { - (new ModelUpdater()).start(); - } else if (line.startsWith("SelectionChanged: ")) { - (new SelectionUpdater()).start(); - } else if (line.startsWith("Trajectory residue network info:")) { - (new NetworkUpdater(line)).start(); - } - } - return; - } - - private void chimeraCommandRead(String command) throws IOException { - // Generally -- looking for: - // CMD command - // ........ - // END - // We return the text in between - List reply = new ArrayList(); - boolean updateModels = false; - boolean updateSelection = false; - boolean importNetwork = false; - String line = null; - - synchronized (replyLog) { - while ((line = lineReader.readLine()) != null) { - // System.out.println("From Chimera (" + command + ") -->" + line); - if (line.startsWith("CMD")) { - logger.warn("Got unexpected command from Chimera: " + line); - - } else if (line.startsWith("END")) { - break; - } - if (line.startsWith("ModelChanged: ")) { - updateModels = true; - } else if (line.startsWith("SelectionChanged: ")) { - updateSelection = true; - } else if (line.length() == 0) { - continue; - } else if (!line.startsWith("CMD")) { - reply.add(line); - } else if (line.startsWith("Trajectory residue network info:")) { - importNetwork = true; - } - } - replyLog.put(command, reply); - } - if (updateModels) + String line = null; + while ((line = lineReader.readLine()) != null) + { + // System.out.println("From Chimera-->" + line); + if (line.startsWith("CMD")) + { + chimeraCommandRead(line.substring(4)); + } + else if (line.startsWith("ModelChanged: ")) + { + (new ModelUpdater()).start(); + } + else if (line.startsWith("SelectionChanged: ")) + { + (new SelectionUpdater()).start(); + } + else if (line.startsWith("Trajectory residue network info:")) + { + (new NetworkUpdater(line)).start(); + } + } + return; + } + + private void chimeraCommandRead(String command) throws IOException + { + // Generally -- looking for: + // CMD command + // ........ + // END + // We return the text in between + List reply = new ArrayList(); + boolean updateModels = false; + boolean updateSelection = false; + boolean importNetwork = false; + String line = null; + + synchronized (replyLog) + { + while ((line = lineReader.readLine()) != null) + { + // System.out.println("From Chimera (" + command + ") -->" + line); + if (line.startsWith("CMD")) + { + logger.warn("Got unexpected command from Chimera: " + line); + + } + else if (line.startsWith("END")) + { + break; + } + if (line.startsWith("ModelChanged: ")) + { + updateModels = true; + } + else if (line.startsWith("SelectionChanged: ")) + { + updateSelection = true; + } + else if (line.length() == 0) + { + continue; + } + else if (!line.startsWith("CMD")) + { + reply.add(line); + } + else if (line.startsWith("Trajectory residue network info:")) + { + importNetwork = true; + } + } + replyLog.put(command, reply); + } + if (updateModels) { (new ModelUpdater()).start(); } - if (updateSelection) + if (updateSelection) { (new SelectionUpdater()).start(); } - if (importNetwork) { - (new NetworkUpdater(line)).start(); - } - return; - } - - /** - * Model updater thread - */ - class ModelUpdater extends Thread { - - public ModelUpdater() { - } - - public void run() { - structureManager.updateModels(); - structureManager.modelChanged(); - } - } - - /** - * Selection updater thread - */ - class SelectionUpdater extends Thread { - - public SelectionUpdater() { - } - - public void run() { - try { - logger.info("Responding to chimera selection"); - structureManager.chimeraSelectionChanged(); - } catch (Exception e) { - logger.warn("Could not update selection", e); - } - } - } - - /** - * Selection updater thread - */ - class NetworkUpdater extends Thread { - - private String line; - - public NetworkUpdater(String line) { - this.line = line; - } - - public void run() { - try { -// ((TaskManager) structureManager.getService(TaskManager.class)) -// .execute(new ImportTrajectoryRINTaskFactory(structureManager, line) -// .createTaskIterator()); - } catch (Exception e) { - logger.warn("Could not import trajectory network", e); - } - } - } + if (importNetwork) + { + (new NetworkUpdater(line)).start(); + } + return; + } + + /** + * Model updater thread + */ + class ModelUpdater extends Thread + { + + public ModelUpdater() + { + } + + public void run() + { + structureManager.updateModels(); + structureManager.modelChanged(); + } + } + + /** + * Selection updater thread + */ + class SelectionUpdater extends Thread + { + + public SelectionUpdater() + { + } + + public void run() + { + try + { + logger.info("Responding to chimera selection"); + structureManager.chimeraSelectionChanged(); + } catch (Exception e) + { + logger.warn("Could not update selection", e); + } + } + } + + /** + * Selection updater thread + */ + class NetworkUpdater extends Thread + { + + private String line; + + public NetworkUpdater(String line) + { + this.line = line; + } + + public void run() + { + try + { + // ((TaskManager) structureManager.getService(TaskManager.class)) + // .execute(new ImportTrajectoryRINTaskFactory(structureManager, line) + // .createTaskIterator()); + } catch (Exception e) + { + logger.warn("Could not import trajectory network", e); + } + } + } + + /** + * Set a flag that this thread should clean up and exit. + */ + public void requestStop() + { + this.stopMe = true; + } } diff --git a/src/jalview/analysis/AlignmentUtils.java b/src/jalview/analysis/AlignmentUtils.java index 929a855..6385fa7 100644 --- a/src/jalview/analysis/AlignmentUtils.java +++ b/src/jalview/analysis/AlignmentUtils.java @@ -20,6 +20,7 @@ */ package jalview.analysis; +import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; @@ -121,6 +122,16 @@ public class AlignmentUtils } AlignmentI newAl = new jalview.datamodel.Alignment( sq.toArray(new SequenceI[0])); + for (SequenceI s : sq) + { + if (s.getAnnotation() != null) + { + for (AlignmentAnnotation aa : s.getAnnotation()) + { + newAl.addAnnotation(aa); + } + } + } newAl.setDataset(core.getDataset()); return newAl; } diff --git a/src/jalview/analysis/Conservation.java b/src/jalview/analysis/Conservation.java index 4d64685..66a6d78 100755 --- a/src/jalview/analysis/Conservation.java +++ b/src/jalview/analysis/Conservation.java @@ -71,6 +71,8 @@ public class Conservation int[][] cons2; + private String[] consSymbs; + /** * Creates a new Conservation object. * @@ -366,17 +368,17 @@ public class Conservation { consString.append('-'); } - + consSymbs = new String[end-start+1]; for (int i = start; i <= end; i++) { gapcons = countConsNGaps(i); totGaps = gapcons[1]; pgaps = ((float) totGaps * 100) / (float) sequences.length; - + consSymbs[i-start]=new String(); + if (percentageGaps > pgaps) { resultHash = total[i - start]; - // Now find the verdict count = 0; enumeration = resultHash.keys(); @@ -385,12 +387,12 @@ public class Conservation { type = (String) enumeration.nextElement(); result = (Integer) resultHash.get(type); - // Do we want to count +ve conservation or +ve and -ve cons.? if (consflag) { if (result.intValue() == 1) { + consSymbs[i-start] = type+" "+consSymbs[i-start]; count++; } } @@ -398,6 +400,14 @@ public class Conservation { if (result.intValue() != -1) { + { + if (result.intValue()==0) { + consSymbs[i-start] = consSymbs[i-start]+ " !"+type; + } else { + consSymbs[i-start] = type+" "+consSymbs[i-start]; + } + } + count++; } } @@ -683,7 +693,7 @@ public class Conservation float vprop = value - min; vprop /= max; conservation.annotations[i] = new Annotation(String.valueOf(c), - String.valueOf(value), ' ', value, new Color(minR + consSymbs[i-start], ' ', value, new Color(minR + (maxR * vprop), minG + (maxG * vprop), minB + (maxB * vprop))); diff --git a/src/jalview/analysis/Finder.java b/src/jalview/analysis/Finder.java index 96151d7..b87c170 100644 --- a/src/jalview/analysis/Finder.java +++ b/src/jalview/analysis/Finder.java @@ -188,7 +188,7 @@ public class Finder { continue; } - +// if invalid string used, then regex has no matched to/from int sres = seq .findPosition(resIndex + Integer.parseInt(spaces.elementAt(resIndex) diff --git a/src/jalview/analysis/NJTree.java b/src/jalview/analysis/NJTree.java index a8ca3f7..099400e 100644 --- a/src/jalview/analysis/NJTree.java +++ b/src/jalview/analysis/NJTree.java @@ -20,13 +20,21 @@ */ package jalview.analysis; -import java.util.*; - import jalview.api.analysis.ScoreModelI; -import jalview.datamodel.*; -import jalview.io.*; -import jalview.schemes.*; -import jalview.util.*; +import jalview.datamodel.AlignmentView; +import jalview.datamodel.BinaryNode; +import jalview.datamodel.CigarArray; +import jalview.datamodel.NodeTransformI; +import jalview.datamodel.SeqCigar; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceI; +import jalview.datamodel.SequenceNode; +import jalview.io.NewickFile; +import jalview.schemes.ResidueProperties; + +import java.util.Enumeration; +import java.util.List; +import java.util.Vector; /** * DOCUMENT ME! @@ -210,7 +218,7 @@ public class NJTree * DOCUMENT ME! */ public NJTree(SequenceI[] sequence, AlignmentView seqData, String type, - String pwtype, int start, int end) + String pwtype, ScoreModelI sm, int start, int end) { this.sequence = sequence; this.node = new Vector(); @@ -237,7 +245,7 @@ public class NJTree type = "AV"; } - if (!(pwtype.equals("PID"))) + if (sm == null && !(pwtype.equals("PID"))) { if (ResidueProperties.getScoreMatrix(pwtype) == null) { @@ -257,7 +265,7 @@ public class NJTree noseqs = i++; - distance = findDistances(); + distance = findDistances(sm); // System.err.println("Made distances");// dbg makeLeaves(); // System.err.println("Made leaves");// dbg @@ -315,7 +323,7 @@ public class NJTree for (int j = 0; j < seqs.length; j++) { - seqs[j] = (SequenceI) list.get(j); + seqs[j] = list.get(j); } seqmatcher = new SequenceIdMatcher(seqs); @@ -722,16 +730,18 @@ public class NJTree * * @return similarity matrix used to compute tree */ - public float[][] findDistances() + public float[][] findDistances(ScoreModelI _pwmatrix) { float[][] distance = new float[noseqs][noseqs]; - - // Pairwise substitution score (with no gap penalties) - ScoreModelI _pwmatrix = ResidueProperties.getScoreModel(pwtype); if (_pwmatrix == null) { - _pwmatrix = ResidueProperties.getScoreMatrix("BLOSUM62"); + // Resolve substitution model + _pwmatrix = ResidueProperties.getScoreModel(pwtype); + if (_pwmatrix == null) + { + _pwmatrix = ResidueProperties.getScoreMatrix("BLOSUM62"); + } } distance = _pwmatrix.findDistances(seqData); return distance; @@ -857,12 +867,12 @@ public class NJTree { System.out .println("Leaf = " + ((SequenceI) node.element()).getName()); - System.out.println("Dist " + ((SequenceNode) node).dist); + System.out.println("Dist " + node.dist); System.out.println("Boot " + node.getBootstrap()); } else { - System.out.println("Dist " + ((SequenceNode) node).dist); + System.out.println("Dist " + node.dist); printNode((SequenceNode) node.left()); printNode((SequenceNode) node.right()); } @@ -883,11 +893,11 @@ public class NJTree if ((node.left() == null) && (node.right() == null)) { - float dist = ((SequenceNode) node).dist; + float dist = node.dist; if (dist > maxDistValue) { - maxdist = (SequenceNode) node; + maxdist = node; maxDistValue = dist; } } @@ -1089,9 +1099,9 @@ public class NJTree + ((SequenceI) node.element()).getName()); } - System.out.println(" dist = " + ((SequenceNode) node).dist + " " - + ((SequenceNode) node).count + " " - + ((SequenceNode) node).height); + System.out.println(" dist = " + node.dist + " " + + node.count + " " + + node.height); } /** @@ -1137,13 +1147,13 @@ public class NJTree SequenceNode l = (SequenceNode) node.left(); SequenceNode r = (SequenceNode) node.right(); - ((SequenceNode) node).count = l.count + r.count; - ((SequenceNode) node).ycount = (l.ycount + r.ycount) / 2; + node.count = l.count + r.count; + node.ycount = (l.ycount + r.ycount) / 2; } else { - ((SequenceNode) node).count = 1; - ((SequenceNode) node).ycount = ycount++; + node.count = 1; + node.ycount = ycount++; } _lycount--; } @@ -1282,7 +1292,9 @@ public class NJTree { for (Enumeration nodes = node.elements(); nodes.hasMoreElements(); nodeTransformI .transform((BinaryNode) nodes.nextElement())) + { ; + } } } diff --git a/src/jalview/analysis/SequenceIdMatcher.java b/src/jalview/analysis/SequenceIdMatcher.java index aec7faf..bedce3f 100755 --- a/src/jalview/analysis/SequenceIdMatcher.java +++ b/src/jalview/analysis/SequenceIdMatcher.java @@ -42,10 +42,15 @@ public class SequenceIdMatcher // TODO: deal with ID collisions - SequenceI should be appended to list // associated with this key. names.put(new SeqIdName(seqs[i].getDisplayId(true)), seqs[i]); + SequenceI dbseq = seqs[i]; + while (dbseq.getDatasetSequence()!=null) + { + dbseq = dbseq.getDatasetSequence(); + } // add in any interesting identifiers - if (seqs[i].getDBRef() != null) + if (dbseq.getDBRef() != null) { - DBRefEntry dbr[] = seqs[i].getDBRef(); + DBRefEntry dbr[] = dbseq.getDBRef(); SeqIdName sid = null; for (int r = 0; r < dbr.length; r++) { diff --git a/src/jalview/analysis/scoremodels/FeatureScoreModel.java b/src/jalview/analysis/scoremodels/FeatureScoreModel.java new file mode 100644 index 0000000..e2a8b9a --- /dev/null +++ b/src/jalview/analysis/scoremodels/FeatureScoreModel.java @@ -0,0 +1,138 @@ +package jalview.analysis.scoremodels; + +import jalview.api.analysis.ScoreModelI; +import jalview.api.analysis.ViewBasedAnalysisI; +import jalview.datamodel.AlignmentView; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.util.Comparison; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.List; + +public class FeatureScoreModel implements ScoreModelI, ViewBasedAnalysisI +{ + jalview.api.FeatureRenderer fr; + + @Override + public boolean configureFromAlignmentView( + jalview.api.AlignmentViewPanel view) + { + fr = view.cloneFeatureRenderer(); + return true; + } + + @Override + public float[][] findDistances(AlignmentView seqData) + { + int nofeats = 0; + List dft = Arrays.asList(fr.getDisplayedFeatureTypes()); + + if (dft != null) + { + nofeats = dft.size(); + } + + SequenceI[] sequenceString = seqData.getVisibleAlignment( + Comparison.GapChars.charAt(0)).getSequencesArray(); + int noseqs = sequenceString.length; + int cpwidth = seqData.getWidth(); + float[][] distance = new float[noseqs][noseqs]; + if (nofeats == 0) + { + for (float[] d : distance) + { + for (int i = 0; i < d.length; d[i++] = 0f) + { + ; + } + } + return distance; + } + float max = 0; + for (int cpos = 0; cpos < cpwidth; cpos++) + { + // get visible features at cpos under view's display settings and compare + // them + List> sfap = new ArrayList>(); + for (int i = 0; i < noseqs; i++) + { + Hashtable types = new Hashtable(); + List sfs = fr.findFeaturesAtRes(sequenceString[i], + sequenceString[i].findPosition(cpos)); + for (SequenceFeature sf : sfs) + { + types.put(sf.getType(), sf); + } + sfap.add(types); + } + for (int i = 0; i < (noseqs - 1); i++) + { + if (cpos == 0) + { + distance[i][i] = 0f; + } + for (int j = i + 1; j < noseqs; j++) + { + int sfcommon = 0; + // compare the two lists of features... + Hashtable fi = sfap.get(i), fk, fj = sfap + .get(j); + if (fi.size() > fj.size()) + { + fk = fj; + } + else + { + fk = fi; + fi = fj; + } + for (String k : fi.keySet()) + { + SequenceFeature sfj = fk.get(k); + if (sfj != null) + { + sfcommon++; + } + } + distance[i][j] += (fi.size() + fk.size() - 2f * sfcommon); + distance[j][i] += distance[i][j]; + } + } + } + for (int i = 0; i < noseqs; i++) + { + for (int j = i + 1; j < noseqs; j++) + { + distance[i][j] /= cpwidth; + distance[j][i] = distance[i][j]; + } + } + return distance; + } + + @Override + public String getName() + { + return "Sequence Feature Similarity"; + } + + @Override + public boolean isDNA() + { + return true; + } + + @Override + public boolean isProtein() + { + return true; + } + + public String toString() + { + return "Score between sequences based on hamming distance between binary vectors marking features displayed at each column"; + } +} diff --git a/src/jalview/api/AlignViewControllerGuiI.java b/src/jalview/api/AlignViewControllerGuiI.java index b9638e5..4010e8b 100644 --- a/src/jalview/api/AlignViewControllerGuiI.java +++ b/src/jalview/api/AlignViewControllerGuiI.java @@ -20,6 +20,8 @@ */ package jalview.api; +import jalview.commands.CommandI; + /** * Interface implemented by gui implementations managing a Jalview Alignment * View @@ -37,4 +39,6 @@ public interface AlignViewControllerGuiI */ void setStatus(String string); + void addHistoryItem(CommandI command); + } diff --git a/src/jalview/api/AlignViewControllerI.java b/src/jalview/api/AlignViewControllerI.java index 35f084f..9bd3f45 100644 --- a/src/jalview/api/AlignViewControllerI.java +++ b/src/jalview/api/AlignViewControllerI.java @@ -64,4 +64,16 @@ public interface AlignViewControllerI boolean markColumnsContainingFeatures(boolean invert, boolean extendCurrent, boolean clearColumns, String featureType); + /** + * sort the alignment or current selection by average score over the given set of features + * @param typ list of feature names or null to use currently displayed features + */ + void sortAlignmentByFeatureScore(String[] typ); + + /** + * sort the alignment or current selection by distribution of the given set of features + * @param typ list of feature names or null to use currently displayed features + */ + void sortAlignmentByFeatureDensity(String[] typ); + } diff --git a/src/jalview/api/AlignViewportI.java b/src/jalview/api/AlignViewportI.java index d8ba30d..24ff7a6 100644 --- a/src/jalview/api/AlignViewportI.java +++ b/src/jalview/api/AlignViewportI.java @@ -200,4 +200,12 @@ public interface AlignViewportI List getVisibleAlignmentAnnotation( boolean selectedOnly); + FeaturesDisplayedI getFeaturesDisplayed(); + + String getSequenceSetId(); + + boolean isShowSequenceFeatures(); + + void setShowSequenceFeatures(boolean b); + } diff --git a/src/jalview/api/AlignmentViewPanel.java b/src/jalview/api/AlignmentViewPanel.java index 7ff3a6a..a68c1f6 100644 --- a/src/jalview/api/AlignmentViewPanel.java +++ b/src/jalview/api/AlignmentViewPanel.java @@ -50,4 +50,14 @@ public interface AlignmentViewPanel extends OOMHandlerI * ensuring the alignment is still visible. */ void adjustAnnotationHeight(); + + FeatureRenderer getFeatureRenderer(); + + FeatureRenderer cloneFeatureRenderer(); + + /** + * + * @return displayed name for the view + */ + String getViewName(); } diff --git a/src/jalview/api/FeatureRenderer.java b/src/jalview/api/FeatureRenderer.java index 679cded..4fd89c1 100644 --- a/src/jalview/api/FeatureRenderer.java +++ b/src/jalview/api/FeatureRenderer.java @@ -20,9 +20,13 @@ */ package jalview.api; +import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import java.awt.Color; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; /** * Abstract feature renderer interface @@ -37,4 +41,38 @@ public interface FeatureRenderer void featuresAdded(); + Object getFeatureStyle(String ft); + + void setColour(String ft, Object ggc); + + AlignViewportI getViewport(); + + FeaturesDisplayedI getFeaturesDisplayed(); + + Map getFeatureColours(); + + void findAllFeatures(boolean newMadeVisible); + + Map getDisplayedFeatureCols(); + + List getFeatureGroups(); + + List getGroups(boolean visible); + + void setGroupVisibility(List toset, boolean visible); + + void setGroupVisibility(String group, boolean visible); + + List findFeaturesAtRes(SequenceI sequence, int res); + + boolean isTransparencyAvailable(); + + String[] getDisplayedFeatureTypes(); + + String[] getDisplayedFeatureGroups(); + + void setAllVisible(List featureTypes); + + void setVisible(String featureType); + } diff --git a/src/jalview/api/FeatureSettingsControllerI.java b/src/jalview/api/FeatureSettingsControllerI.java new file mode 100644 index 0000000..c718e36 --- /dev/null +++ b/src/jalview/api/FeatureSettingsControllerI.java @@ -0,0 +1,6 @@ +package jalview.api; + +public interface FeatureSettingsControllerI +{ + +} diff --git a/src/jalview/api/FeatureSettingsModelI.java b/src/jalview/api/FeatureSettingsModelI.java new file mode 100644 index 0000000..c148f3f --- /dev/null +++ b/src/jalview/api/FeatureSettingsModelI.java @@ -0,0 +1,6 @@ +package jalview.api; + +public interface FeatureSettingsModelI +{ + +} diff --git a/src/jalview/api/FeaturesDisplayedI.java b/src/jalview/api/FeaturesDisplayedI.java new file mode 100644 index 0000000..9ed5ae5 --- /dev/null +++ b/src/jalview/api/FeaturesDisplayedI.java @@ -0,0 +1,29 @@ +package jalview.api; + +import java.util.Collection; +import java.util.Iterator; + +public interface FeaturesDisplayedI +{ + + Iterator getVisibleFeatures(); + + boolean isVisible(String featureType); + + boolean areVisible(Collection featureTypes); + + void clear(); + + void setVisible(String featureType); + + void setAllVisible(Collection featureTypes); + + boolean isRegistered(String type); + + void setAllRegisteredVisible(); + + int getVisibleFeatureCount(); + + int getRegisterdFeaturesCount(); + +} diff --git a/src/jalview/api/SequenceRenderer.java b/src/jalview/api/SequenceRenderer.java index fbd5e4a..0ca1758 100644 --- a/src/jalview/api/SequenceRenderer.java +++ b/src/jalview/api/SequenceRenderer.java @@ -29,4 +29,6 @@ public interface SequenceRenderer Color getResidueBoxColour(SequenceI sequenceI, int r); + Color getResidueColour(SequenceI seq, int position, FeatureRenderer fr); + } diff --git a/src/jalview/api/analysis/ViewBasedAnalysisI.java b/src/jalview/api/analysis/ViewBasedAnalysisI.java new file mode 100644 index 0000000..3404afc --- /dev/null +++ b/src/jalview/api/analysis/ViewBasedAnalysisI.java @@ -0,0 +1,17 @@ +package jalview.api.analysis; + +import jalview.api.AlignViewportI; +import jalview.api.AlignmentViewPanel; + +public interface ViewBasedAnalysisI +{ + + /** + * Parameterise the analysis model using the current view + * @param view + * @return true if model is applicable and calculation should proceed + */ + + boolean configureFromAlignmentView(AlignmentViewPanel view); + +} diff --git a/src/jalview/appletgui/APopupMenu.java b/src/jalview/appletgui/APopupMenu.java index 98a4a1c..aa1ab21 100644 --- a/src/jalview/appletgui/APopupMenu.java +++ b/src/jalview/appletgui/APopupMenu.java @@ -673,7 +673,7 @@ public class APopupMenu extends java.awt.PopupMenu implements features, true, ap)) { ap.alignFrame.sequenceFeatures.setState(true); - ap.av.showSequenceFeatures(true); + ap.av.setShowSequenceFeatures(true);; ap.highlightSearchResults(null); } } @@ -732,7 +732,7 @@ public class APopupMenu extends java.awt.PopupMenu implements true, true, false, - (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.minmax + (ap.seqPanel.seqCanvas.fr != null) ? ap.seqPanel.seqCanvas.fr.getMinMax() : null); contents.append("

    "); } diff --git a/src/jalview/appletgui/AlignFrame.java b/src/jalview/appletgui/AlignFrame.java index ed64215..9fb91ed 100644 --- a/src/jalview/appletgui/AlignFrame.java +++ b/src/jalview/appletgui/AlignFrame.java @@ -24,6 +24,7 @@ import jalview.analysis.AlignmentSorter; import jalview.api.AlignViewControllerGuiI; import jalview.api.AlignViewControllerI; import jalview.api.SequenceStructureBinding; +import jalview.api.FeatureRenderer; import jalview.bin.JalviewLite; import jalview.commands.CommandI; import jalview.commands.EditCommand; @@ -89,9 +90,12 @@ import java.awt.event.WindowEvent; import java.io.IOException; import java.net.URL; import java.net.URLEncoder; +import java.util.Arrays; import java.util.Enumeration; import java.util.Hashtable; +import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.StringTokenizer; import java.util.Vector; @@ -285,7 +289,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, { featuresFile = new jalview.io.FeaturesFile(file, type) .parse(viewport.getAlignment(), alignPanel.seqPanel.seqCanvas - .getFeatureRenderer().featureColours, featureLinks, + .getFeatureRenderer().getFeatureColours(), featureLinks, true, viewport.applet.getDefaultParameter( "relaxedidmatch", false)); } catch (Exception ex) @@ -301,9 +305,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, } if (autoenabledisplay) { - viewport.showSequenceFeatures = true; + viewport.setShowSequenceFeatures(true); sequenceFeatures.setState(true); } + if (alignPanel.seqPanel.seqCanvas.fr != null) + { + // update the min/max ranges where necessary + alignPanel.seqPanel.seqCanvas.fr.findAllFeatures(true); + } if (viewport.featureSettings != null) { viewport.featureSettings.refreshTable(); @@ -729,7 +738,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, } else if (evt.getSource() == sequenceFeatures) { - viewport.showSequenceFeatures(sequenceFeatures.getState()); + viewport.setShowSequenceFeatures(sequenceFeatures.getState()); alignPanel.seqPanel.seqCanvas.repaint(); } else if (evt.getSource() == conservationMenuItem) @@ -1210,20 +1219,13 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, return annotation; } - private Hashtable getDisplayedFeatureCols() + private Map getDisplayedFeatureCols() { if (alignPanel.getFeatureRenderer() != null - && viewport.featuresDisplayed != null) + && viewport.getFeaturesDisplayed()!= null) { - FeatureRenderer fr = alignPanel.getFeatureRenderer(); - Hashtable fcols = new Hashtable(); - Enumeration en = viewport.featuresDisplayed.keys(); - while (en.hasMoreElements()) - { - Object col = en.nextElement(); - fcols.put(col, fr.featureColours.get(col)); - } - return fcols; + return alignPanel.getFeatureRenderer().getDisplayedFeatureCols(); + } return null; } @@ -1429,6 +1431,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, /** * TODO: JAL-1104 */ + @Override public void addHistoryItem(CommandI command) { if (command.getSize() > 0) @@ -2271,7 +2274,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, if (alignPanel != null && (fr = alignPanel.getFeatureRenderer()) != null) { - return fr.getGroups(); + List gps = fr.getFeatureGroups(); + int p=0; + String[] _gps = new String[gps.size()]; + for (Object gp:gps) + { + _gps[p++] = gp.toString(); + } + return _gps; } return null; } @@ -2289,7 +2299,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, if (alignPanel != null && (fr = alignPanel.getFeatureRenderer()) != null) { - return fr.getGroups(visible); + List gps = fr.getGroups(visible); + int p=0; + String[] _gps = new String[gps.size()]; + for (Object gp:gps) + { + _gps[p++] = gp.toString(); + } + return _gps; } return null; } @@ -2306,11 +2323,12 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener, { FeatureRenderer fr = null; this.sequenceFeatures.setState(true); - viewport.showSequenceFeatures(true); + viewport.setShowSequenceFeatures(true); if (alignPanel != null && (fr = alignPanel.getFeatureRenderer()) != null) { - fr.setGroupState(groups, state); + + fr.setGroupVisibility((List)Arrays.asList(groups), state); alignPanel.seqPanel.seqCanvas.repaint(); if (alignPanel.overviewPanel != null) { diff --git a/src/jalview/appletgui/AlignViewport.java b/src/jalview/appletgui/AlignViewport.java index 7400122..9a15e10 100644 --- a/src/jalview/appletgui/AlignViewport.java +++ b/src/jalview/appletgui/AlignViewport.java @@ -58,8 +58,6 @@ public class AlignViewport extends AlignmentViewport implements boolean renderGaps = true; - boolean showSequenceFeatures = false; - boolean showAnnotation = true; boolean upperCasebold = false; @@ -86,10 +84,6 @@ public class AlignViewport extends AlignmentViewport implements boolean scaleRightWrapped = true; - // The following vector holds the features which are - // currently visible, in the correct order or rendering - public Hashtable featuresDisplayed; - boolean showHiddenMarkers = true; public jalview.bin.JalviewLite applet; @@ -256,16 +250,6 @@ public class AlignViewport extends AlignmentViewport implements } - public void showSequenceFeatures(boolean b) - { - showSequenceFeatures = b; - } - - public boolean getShowSequenceFeatures() - { - return showSequenceFeatures; - } - /** * get the consensus sequence as displayed under the PID consensus annotation * row. diff --git a/src/jalview/appletgui/AlignmentPanel.java b/src/jalview/appletgui/AlignmentPanel.java index 02ad0cd..5308a42 100644 --- a/src/jalview/appletgui/AlignmentPanel.java +++ b/src/jalview/appletgui/AlignmentPanel.java @@ -20,13 +20,25 @@ */ package jalview.appletgui; -import java.awt.*; -import java.awt.event.*; - import jalview.api.AlignmentViewPanel; -import jalview.datamodel.*; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.SearchResults; +import jalview.datamodel.SequenceI; import jalview.structure.StructureSelectionManager; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.Scrollbar; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; + public class AlignmentPanel extends Panel implements AdjustmentListener, AlignmentViewPanel { @@ -145,12 +157,18 @@ public class AlignmentPanel extends Panel implements AdjustmentListener, { return seqPanel.seqCanvas.sr; } - - public FeatureRenderer getFeatureRenderer() + @Override + public jalview.api.FeatureRenderer getFeatureRenderer() { return seqPanel.seqCanvas.fr; } - + @Override + public jalview.api.FeatureRenderer cloneFeatureRenderer() + { + FeatureRenderer nfr = new FeatureRenderer(av); + nfr.transferSettings(seqPanel.seqCanvas.fr); + return nfr; + } public void alignmentChanged() { av.alignmentChanged(this); @@ -965,6 +983,12 @@ public class AlignmentPanel extends Panel implements AdjustmentListener, } @Override + public String getViewName() + { + return getName(); + } + + @Override public StructureSelectionManager getStructureSelectionManager() { return StructureSelectionManager diff --git a/src/jalview/appletgui/AppletJmol.java b/src/jalview/appletgui/AppletJmol.java index 42fbd70..322a60f 100644 --- a/src/jalview/appletgui/AppletJmol.java +++ b/src/jalview/appletgui/AppletJmol.java @@ -519,7 +519,7 @@ public class AppletJmol extends EmbmenuFrame implements else if (evt.getSource() == seqColour) { setEnabled(seqColour); - jmb.colourBySequence(ap.av.getShowSequenceFeatures(), ap); + jmb.colourBySequence(ap.av.isShowSequenceFeatures(), ap); } else if (!allChainsSelected) centerViewer(); @@ -547,7 +547,7 @@ public class AppletJmol extends EmbmenuFrame implements public void updateColours(Object source) { AlignmentPanel ap = (AlignmentPanel) source; - jmb.colourBySequence(ap.av.getShowSequenceFeatures(), ap); + jmb.colourBySequence(ap.av.isShowSequenceFeatures(), ap); } public void updateTitleAndMenus() @@ -558,7 +558,7 @@ public class AppletJmol extends EmbmenuFrame implements return; } setChainMenuItems(jmb.chainNames); - jmb.colourBySequence(ap.av.getShowSequenceFeatures(), ap); + jmb.colourBySequence(ap.av.isShowSequenceFeatures(), ap); setTitle(jmb.getViewerTitle()); } diff --git a/src/jalview/appletgui/AppletJmolBinding.java b/src/jalview/appletgui/AppletJmolBinding.java index 650693d..d2a6e6c 100644 --- a/src/jalview/appletgui/AppletJmolBinding.java +++ b/src/jalview/appletgui/AppletJmolBinding.java @@ -52,7 +52,7 @@ class AppletJmolBinding extends jalview.ext.jmol.JalviewJmolBinding AlignmentViewPanel alignment) { AlignmentPanel ap = (AlignmentPanel) alignment; - if (appletJmolBinding.ap.av.showSequenceFeatures) + if (appletJmolBinding.ap.av.isShowSequenceFeatures()) { if (appletJmolBinding.fr == null) { @@ -105,7 +105,7 @@ class AppletJmolBinding extends jalview.ext.jmol.JalviewJmolBinding public void updateColours(Object source) { AlignmentPanel ap = (AlignmentPanel) source; - colourBySequence(ap.av.getShowSequenceFeatures(), ap); + colourBySequence(ap.av.isShowSequenceFeatures(), ap); } public void showUrl(String url) diff --git a/src/jalview/appletgui/ExtJmol.java b/src/jalview/appletgui/ExtJmol.java index 6389250..1efb971 100644 --- a/src/jalview/appletgui/ExtJmol.java +++ b/src/jalview/appletgui/ExtJmol.java @@ -78,7 +78,7 @@ public class ExtJmol extends JalviewJmolBinding public FeatureRenderer getFeatureRenderer(AlignmentViewPanel alignment) { AlignmentPanel ap = (AlignmentPanel) alignment; - if (ap.av.showSequenceFeatures) + if (ap.av.isShowSequenceFeatures()) { return ap.getFeatureRenderer(); } diff --git a/src/jalview/appletgui/FeatureColourChooser.java b/src/jalview/appletgui/FeatureColourChooser.java index 32ffdbf..c87803c 100644 --- a/src/jalview/appletgui/FeatureColourChooser.java +++ b/src/jalview/appletgui/FeatureColourChooser.java @@ -73,10 +73,10 @@ public class FeatureColourChooser extends Panel implements ActionListener, { this.type = type; fr = frenderer; - float mm[] = ((float[][]) fr.minmax.get(type))[0]; + float mm[] = ((float[][]) fr.getMinMax().get(type))[0]; min = mm[0]; max = mm[1]; - oldcs = fr.featureColours.get(type); + oldcs = fr.getFeatureColours().get(type); if (oldcs instanceof GraduatedColor) { cs = new GraduatedColor((GraduatedColor) oldcs, min, max); @@ -130,7 +130,7 @@ public class FeatureColourChooser extends Panel implements ActionListener, { // cancel reset(); - PaintRefresher.Refresh(this, fr.av.getSequenceSetId()); + PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId()); frame.setVisible(false); } } @@ -289,7 +289,7 @@ public class FeatureColourChooser extends Panel implements ActionListener, threshline.value = (float) slider.getValue() / 1000f; cs.setThresh(threshline.value); changeColour(); - PaintRefresher.Refresh(this, fr.av.getSequenceSetId()); + PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId()); // ap.paintAlignment(false); } @@ -402,16 +402,16 @@ public class FeatureColourChooser extends Panel implements ActionListener, } } - fr.featureColours.put(type, acg); + fr.setColour(type, acg); cs = acg; - PaintRefresher.Refresh(this, fr.av.getSequenceSetId()); + PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId()); // ap.paintAlignment(false); } void reset() { - fr.featureColours.put(type, oldcs); - PaintRefresher.Refresh(this, fr.av.getSequenceSetId()); + fr.setColour(type, oldcs); + PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId()); // ap.paintAlignment(true); } @@ -433,7 +433,7 @@ public class FeatureColourChooser extends Panel implements ActionListener, } else { - PaintRefresher.Refresh(this, fr.av.getSequenceSetId()); + PaintRefresher.Refresh(this, fr.getViewport().getSequenceSetId()); } // ap.paintAlignment(true); } diff --git a/src/jalview/appletgui/FeatureRenderer.java b/src/jalview/appletgui/FeatureRenderer.java index 29c3ac5..dd2b873 100644 --- a/src/jalview/appletgui/FeatureRenderer.java +++ b/src/jalview/appletgui/FeatureRenderer.java @@ -21,15 +21,14 @@ package jalview.appletgui; import java.util.*; - import java.awt.*; - import java.awt.event.*; import jalview.datamodel.*; import jalview.schemes.AnnotationColourGradient; import jalview.schemes.GraduatedColor; import jalview.util.MessageManager; +import jalview.viewmodel.seqfeatures.FeaturesDisplayed; /** * DOCUMENT ME! @@ -37,34 +36,13 @@ import jalview.util.MessageManager; * @author $author$ * @version $Revision$ */ -public class FeatureRenderer implements jalview.api.FeatureRenderer +public class FeatureRenderer extends jalview.renderer.seqfeatures.FeatureRenderer { - AlignViewport av; - - Hashtable featureColours = new Hashtable(); - - // A higher level for grouping features of a - // particular type - Hashtable featureGroups = null; // Holds web links for feature groups and feature types // in the form label|link Hashtable featureLinks = null; - // This is actually an Integer held in the hashtable, - // Retrieved using the key feature type - Object currentColour; - - String[] renderOrder; - - FontMetrics fm; - - int charOffset; - - float transparency = 1f; - - TransparencySetter transparencySetter = null; - /** * Creates a new FeatureRenderer object. * @@ -73,39 +51,10 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer */ public FeatureRenderer(AlignViewport av) { + super(); this.av = av; - if (!System.getProperty("java.version").startsWith("1.1")) - { - transparencySetter = new TransparencySetter(); - } - } - - public void transferSettings(FeatureRenderer fr) - { - renderOrder = fr.renderOrder; - featureGroups = fr.featureGroups; - featureColours = fr.featureColours; - transparency = fr.transparency; - if (av != null && fr.av != null && fr.av != av) - { - if (fr.av.featuresDisplayed != null) - { - if (av.featuresDisplayed == null) - { - av.featuresDisplayed = new Hashtable(); - } - else - { - av.featuresDisplayed.clear(); - } - Enumeration en = fr.av.featuresDisplayed.keys(); - while (en.hasMoreElements()) - { - av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE); - } - } - } + setTransparencyAvailable(!System.getProperty("java.version").startsWith("1.1")); } static String lastFeatureAdded; @@ -452,6 +401,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer } ffile.parseDescriptionHTML(sf, false); + setVisible(lastFeatureAdded); // if user edited name then make sure new type is visible } if (deleteFeature) { @@ -472,36 +422,17 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer ffile.parseDescriptionHTML(features[i], false); } - if (av.featuresDisplayed == null) - { - av.featuresDisplayed = new Hashtable(); - } - - if (featureGroups == null) - { - featureGroups = new Hashtable(); - } - col = colourPanel.getBackground(); // setColour(lastFeatureAdded, fcol); if (lastFeatureGroupAdded != null) { - featureGroups.put(lastFeatureGroupAdded, new Boolean(true)); - } - if (fcol instanceof Color) - { - setColour(lastFeatureAdded, fcol); + setGroupVisibility(lastFeatureGroupAdded, true); } - av.featuresDisplayed.put(lastFeatureAdded, - getFeatureStyle(lastFeatureAdded)); - - findAllFeatures(); - - String[] tro = new String[renderOrder.length]; - tro[0] = renderOrder[renderOrder.length - 1]; - System.arraycopy(renderOrder, 0, tro, 1, renderOrder.length - 1); - renderOrder = tro; + setColour(lastFeatureAdded, fcol); + setVisible(lastFeatureAdded); + findAllFeatures(false); // different to original applet behaviour ? + // findAllFeatures(); } else { @@ -510,9 +441,9 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer } } // refresh the alignment and the feature settings dialog - if (av.featureSettings != null) + if (((jalview.appletgui.AlignViewport) av).featureSettings != null) { - av.featureSettings.refreshTable(); + ((jalview.appletgui.AlignViewport) av).featureSettings.refreshTable(); } // findAllFeatures(); @@ -520,759 +451,4 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer return true; } - - public Color findFeatureColour(Color initialCol, SequenceI seq, int i) - { - overview = true; - if (!av.showSequenceFeatures) - { - return initialCol; - } - - lastSeq = seq; - sequenceFeatures = lastSeq.getSequenceFeatures(); - if (sequenceFeatures == null) - { - return initialCol; - } - - sfSize = sequenceFeatures.length; - - if (jalview.util.Comparison.isGap(lastSeq.getCharAt(i))) - { - return Color.white; - } - - currentColour = null; - - drawSequence(null, lastSeq, lastSeq.findPosition(i), -1, -1); - - if (currentColour == null) - { - return initialCol; - } - - return new Color(((Integer) currentColour).intValue()); - } - - /** - * This is used by the Molecule Viewer to get the accurate colour of the - * rendered sequence - */ - boolean overview = false; - - /** - * DOCUMENT ME! - * - * @param g - * DOCUMENT ME! - * @param seq - * DOCUMENT ME! - * @param sg - * DOCUMENT ME! - * @param start - * DOCUMENT ME! - * @param end - * DOCUMENT ME! - * @param x1 - * DOCUMENT ME! - * @param y1 - * DOCUMENT ME! - * @param width - * DOCUMENT ME! - * @param height - * DOCUMENT ME! - */ - // String type; - // SequenceFeature sf; - SequenceI lastSeq; - - SequenceFeature[] sequenceFeatures; - - int sfSize, sfindex, spos, epos; - - synchronized public void drawSequence(Graphics g, SequenceI seq, - int start, int end, int y1) - { - if (seq.getSequenceFeatures() == null - || seq.getSequenceFeatures().length == 0) - { - return; - } - - if (transparencySetter != null && g != null) - { - transparencySetter.setTransparency(g, transparency); - } - - if (lastSeq == null || seq != lastSeq - || sequenceFeatures != seq.getSequenceFeatures()) - { - lastSeq = seq; - sequenceFeatures = seq.getSequenceFeatures(); - sfSize = sequenceFeatures.length; - } - - if (av.featuresDisplayed == null || renderOrder == null) - { - findAllFeatures(); - if (av.featuresDisplayed.size() < 1) - { - return; - } - - sequenceFeatures = seq.getSequenceFeatures(); - sfSize = sequenceFeatures.length; - } - if (!overview) - { - spos = lastSeq.findPosition(start); - epos = lastSeq.findPosition(end); - if (g != null) - { - fm = g.getFontMetrics(); - } - } - String type; - for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++) - { - type = renderOrder[renderIndex]; - if (!av.featuresDisplayed.containsKey(type)) - { - continue; - } - - // loop through all features in sequence to find - // current feature to render - for (sfindex = 0; sfindex < sfSize; sfindex++) - { - if (!sequenceFeatures[sfindex].type.equals(type)) - { - continue; - } - - if (featureGroups != null - && sequenceFeatures[sfindex].featureGroup != null - && featureGroups - .containsKey(sequenceFeatures[sfindex].featureGroup) - && !((Boolean) featureGroups - .get(sequenceFeatures[sfindex].featureGroup)) - .booleanValue()) - { - continue; - } - - if (!overview - && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex] - .getEnd() < spos)) - { - continue; - } - - if (overview) - { - if (sequenceFeatures[sfindex].begin <= start - && sequenceFeatures[sfindex].end >= start) - { - currentColour = new Integer( - getColour(sequenceFeatures[sfindex]).getRGB());// av.featuresDisplayed - // .get(sequenceFeatures[sfindex].type); - } - - } - else if (sequenceFeatures[sfindex].type.equals("disulfide bond")) - { - - renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - getColour(sequenceFeatures[sfindex]) - // new Color(((Integer) av.featuresDisplayed - // .get(sequenceFeatures[sfindex].type)).intValue()) - , start, end, y1); - renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]) - // new Color(((Integer) av.featuresDisplayed - // .get(sequenceFeatures[sfindex].type)).intValue()) - , start, end, y1); - - } - else - { - if (showFeature(sequenceFeatures[sfindex])) - { - renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]), start, end, y1); - } - } - - } - } - - if (transparencySetter != null && g != null) - { - transparencySetter.setTransparency(g, 1.0f); - } - } - - char s; - - int i; - - void renderFeature(Graphics g, SequenceI seq, int fstart, int fend, - Color featureColour, int start, int end, int y1) - { - - if (((fstart <= end) && (fend >= start))) - { - if (fstart < start) - { // fix for if the feature we have starts before the sequence start, - fstart = start; // but the feature end is still valid!! - } - - if (fend >= end) - { - fend = end; - } - - for (i = fstart; i <= fend; i++) - { - s = seq.getCharAt(i); - - if (jalview.util.Comparison.isGap(s)) - { - continue; - } - - g.setColor(featureColour); - - g.fillRect((i - start) * av.charWidth, y1, av.charWidth, - av.charHeight); - - if (!av.validCharWidth) - { - continue; - } - - g.setColor(Color.white); - charOffset = (av.charWidth - fm.charWidth(s)) / 2; - g.drawString(String.valueOf(s), charOffset - + (av.charWidth * (i - start)), (y1 + av.charHeight) - - av.charHeight / 5); // pady = height / 5; - - } - } - } - - Hashtable minmax = null; - - /** - * Called when alignment in associated view has new/modified features to - * discover and display. - * - */ - public void featuresAdded() - { - lastSeq = null; - findAllFeatures(); - } - - /** - * find all features on the alignment - */ - void findAllFeatures() - { - jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(); - - av.featuresDisplayed = new Hashtable(); - Vector allfeatures = new Vector(); - minmax = new Hashtable(); - AlignmentI alignment = av.getAlignment(); - for (int i = 0; i < alignment.getHeight(); i++) - { - SequenceFeature[] features = alignment.getSequenceAt(i) - .getSequenceFeatures(); - - if (features == null) - { - continue; - } - - int index = 0; - while (index < features.length) - { - if (features[index].begin == 0 && features[index].end == 0) - { - index++; - continue; - } - if (!av.featuresDisplayed.containsKey(features[index].getType())) - { - if (getColour(features[index].getType()) == null) - { - featureColours.put(features[index].getType(), - ucs.createColourFromName(features[index].getType())); - } - - av.featuresDisplayed.put(features[index].getType(), new Integer( - getColour(features[index].getType()).getRGB())); - allfeatures.addElement(features[index].getType()); - } - if (features[index].score != Float.NaN) - { - int nonpos = features[index].getBegin() >= 1 ? 0 : 1; - float[][] mm = (float[][]) minmax.get(features[index].getType()); - if (mm == null) - { - mm = new float[][] - { null, null }; - minmax.put(features[index].getType(), mm); - } - if (mm[nonpos] == null) - { - mm[nonpos] = new float[] - { features[index].score, features[index].score }; - - } - else - { - if (mm[nonpos][0] > features[index].score) - { - mm[nonpos][0] = features[index].score; - } - if (mm[nonpos][1] < features[index].score) - { - mm[nonpos][1] = features[index].score; - } - } - } - - index++; - } - } - - renderOrder = new String[allfeatures.size()]; - Enumeration en = allfeatures.elements(); - int i = allfeatures.size() - 1; - while (en.hasMoreElements()) - { - renderOrder[i] = en.nextElement().toString(); - i--; - } - } - - /** - * get a feature style object for the given type string. Creates a - * java.awt.Color for a featureType with no existing colourscheme. TODO: - * replace return type with object implementing standard abstract colour/style - * interface - * - * @param featureType - * @return java.awt.Color or GraduatedColor - */ - public Object getFeatureStyle(String featureType) - { - Object fc = featureColours.get(featureType); - if (fc == null) - { - jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(); - Color col = ucs.createColourFromName(featureType); - featureColours.put(featureType, fc = col); - } - return fc; - } - - public Color getColour(String featureType) - { - Object fc = getFeatureStyle(featureType); - - if (fc instanceof Color) - { - return (Color) fc; - } - else - { - if (fc instanceof GraduatedColor) - { - return ((GraduatedColor) fc).getMaxColor(); - } - } - throw new Error(MessageManager.formatMessage("error.implementation_error_unrecognised_render_object_for_features_type", new String[]{fc.getClass().getCanonicalName(),featureType})); - } - - /** - * - * @param sequenceFeature - * @return true if feature is visible. - */ - private boolean showFeature(SequenceFeature sequenceFeature) - { - Object fc = getFeatureStyle(sequenceFeature.type); - if (fc instanceof GraduatedColor) - { - return ((GraduatedColor) fc).isColored(sequenceFeature); - } - else - { - return true; - } - } - - /** - * implement graduated colouring for features with scores - * - * @param feature - * @return render colour for the given feature - */ - public Color getColour(SequenceFeature feature) - { - Object fc = getFeatureStyle(feature.getType()); - if (fc instanceof Color) - { - return (Color) fc; - } - else - { - if (fc instanceof GraduatedColor) - { - return ((GraduatedColor) fc).findColor(feature); - } - } - throw new Error("Implementation Error: Unrecognised render object " - + fc.getClass() + " for features of type " + feature.getType()); - } - - public void setColour(String featureType, Object col) - { - // overwrite - // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof - // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null; - // Object c = featureColours.get(featureType); - // if (c == null || c instanceof Color || (c instanceof GraduatedColor && - // !((GraduatedColor)c).getMaxColor().equals(_col))) - { - featureColours.put(featureType, col); - } - } - - public void setFeaturePriority(Object[][] data) - { - // The feature table will display high priority - // features at the top, but theses are the ones - // we need to render last, so invert the data - if (av.featuresDisplayed != null) - { - av.featuresDisplayed.clear(); - } - - /* - * if (visibleNew) { if (av.featuresDisplayed != null) { - * av.featuresDisplayed.clear(); } else { av.featuresDisplayed = new - * Hashtable(); } } if (data == null) { return; } - */ - - renderOrder = new String[data.length]; - - if (data.length > 0) - { - for (int i = 0; i < data.length; i++) - { - String type = data[i][0].toString(); - setColour(type, data[i][1]); - if (((Boolean) data[i][2]).booleanValue()) - { - av.featuresDisplayed.put(type, new Integer(getColour(type) - .getRGB())); - } - - renderOrder[data.length - i - 1] = type; - } - } - } - - /** - * @return a simple list of feature group names or null - */ - public String[] getGroups() - { - buildGroupHash(); - if (featureGroups != null) - { - String[] gps = new String[featureGroups.size()]; - Enumeration gn = featureGroups.keys(); - int i = 0; - while (gn.hasMoreElements()) - { - gps[i++] = (String) gn.nextElement(); - } - return gps; - } - return null; - } - - /** - * get visible or invisible groups - * - * @param visible - * true to return visible groups, false to return hidden ones. - * @return list of groups - */ - public String[] getGroups(boolean visible) - { - buildGroupHash(); - if (featureGroups != null) - { - Vector gp = new Vector(); - - Enumeration gn = featureGroups.keys(); - while (gn.hasMoreElements()) - { - String nm = (String) gn.nextElement(); - Boolean state = (Boolean) featureGroups.get(nm); - if (state.booleanValue() == visible) - { - gp.addElement(nm); - } - } - String[] gps = new String[gp.size()]; - gp.copyInto(gps); - - int i = 0; - while (gn.hasMoreElements()) - { - gps[i++] = (String) gn.nextElement(); - } - return gps; - } - return null; - } - - /** - * set all feature groups in toset to be visible or invisible - * - * @param toset - * group names - * @param visible - * the state of the named groups to set - */ - public void setGroupState(String[] toset, boolean visible) - { - buildGroupHash(); - if (toset != null && toset.length > 0 && featureGroups != null) - { - boolean rdrw = false; - for (int i = 0; i < toset.length; i++) - { - Object st = featureGroups.get(toset[i]); - featureGroups.put(toset[i], new Boolean(visible)); - if (st != null) - { - rdrw = rdrw || (visible != ((Boolean) st).booleanValue()); - } - } - if (rdrw) - { - if (this.av != null) - if (this.av.featureSettings != null) - { - av.featureSettings.rebuildGroups(); - this.av.featureSettings.resetTable(true); - } - else - { - buildFeatureHash(); - } - if (av != null) - { - av.alignmentChanged(null); - } - } - } - } - - ArrayList hiddenGroups = new ArrayList(); - - /** - * analyse alignment for groups and hash tables (used to be embedded in - * FeatureSettings.setTableData) - * - * @return true if features are on the alignment - */ - public boolean buildGroupHash() - { - boolean alignmentHasFeatures = false; - if (featureGroups == null) - { - featureGroups = new Hashtable(); - } - hiddenGroups = new ArrayList(); - hiddenGroups.addAll(featureGroups.keySet()); - ArrayList allFeatures = new ArrayList(); - ArrayList allGroups = new ArrayList(); - SequenceFeature[] tmpfeatures; - String group; - AlignmentI alignment = av.getAlignment(); - for (int i = 0; i < alignment.getHeight(); i++) - { - if (alignment.getSequenceAt(i).getSequenceFeatures() == null) - { - continue; - } - - alignmentHasFeatures = true; - - tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures(); - int index = 0; - while (index < tmpfeatures.length) - { - if (tmpfeatures[index].getFeatureGroup() != null) - { - group = tmpfeatures[index].featureGroup; - // Remove group from the hiddenGroup list - hiddenGroups.remove(group); - if (!allGroups.contains(group)) - { - allGroups.add(group); - - boolean visible = true; - if (featureGroups.containsKey(group)) - { - visible = ((Boolean) featureGroups.get(group)).booleanValue(); - } - else - { - featureGroups.put(group, new Boolean(visible)); - } - } - } - - if (!allFeatures.contains(tmpfeatures[index].getType())) - { - allFeatures.add(tmpfeatures[index].getType()); - } - index++; - } - } - - return alignmentHasFeatures; - } - - /** - * rebuild the featuresDisplayed and renderorder list based on the - * featureGroups hash and any existing display state and force a repaint if - * necessary - * - * @return true if alignment has visible features - */ - public boolean buildFeatureHash() - { - boolean alignmentHasFeatures = false; - if (featureGroups == null) - { - alignmentHasFeatures = buildGroupHash(); - } - if (!alignmentHasFeatures) - return false; - Hashtable fdisp = av.featuresDisplayed; - Vector allFeatures = new Vector(); - SequenceFeature[] tmpfeatures; - String group; - AlignmentI alignment = av.getAlignment(); - for (int i = 0; i < alignment.getHeight(); i++) - { - if (alignment.getSequenceAt(i).getSequenceFeatures() == null) - { - continue; - } - - alignmentHasFeatures = true; - - tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures(); - int index = 0; - while (index < tmpfeatures.length) - { - boolean visible = true; - if (tmpfeatures[index].getFeatureGroup() != null) - { - group = tmpfeatures[index].featureGroup; - if (featureGroups.containsKey(group)) - { - visible = ((Boolean) featureGroups.get(group)).booleanValue(); - } - } - - if (visible && !allFeatures.contains(tmpfeatures[index].getType())) - { - allFeatures.addElement(tmpfeatures[index].getType()); - } - index++; - } - } - if (allFeatures.size() > 0) - { - String[] neworder = new String[allFeatures.size()]; - int p = neworder.length - 1; - for (int i = renderOrder.length - 1; i >= 0; i--) - { - if (allFeatures.contains(renderOrder[i])) - { - neworder[p--] = renderOrder[i]; - allFeatures.removeElement(renderOrder[i]); - } - else - { - av.featuresDisplayed.remove(renderOrder[i]); - } - } - for (int i = allFeatures.size() - 1; i > 0; i++) - { - Object e = allFeatures.elementAt(i); - if (e != null) - { - neworder[p--] = (String) e; - av.featuresDisplayed.put(e, getColour((String) e)); - } - } - renderOrder = neworder; - return true; - } - - return alignmentHasFeatures; - } - - /** - * - * @return the displayed feature type as an array of strings - */ - protected String[] getDisplayedFeatureTypes() - { - String[] typ = null; - synchronized (renderOrder) - { - typ = new String[renderOrder.length]; - System.arraycopy(renderOrder, 0, typ, 0, typ.length); - for (int i = 0; i < typ.length; i++) - { - if (av.featuresDisplayed.get(typ[i]) == null) - { - typ[i] = null; - } - } - } - return typ; - } -} - -class TransparencySetter -{ - void setTransparency(Graphics g, float value) - { - Graphics2D g2 = (Graphics2D) g; - g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, - value)); - } } diff --git a/src/jalview/appletgui/FeatureSettings.java b/src/jalview/appletgui/FeatureSettings.java index cd11a35..4b29f53 100755 --- a/src/jalview/appletgui/FeatureSettings.java +++ b/src/jalview/appletgui/FeatureSettings.java @@ -21,7 +21,7 @@ package jalview.appletgui; import java.util.*; - +import java.util.List; import java.awt.*; import java.awt.event.*; @@ -50,8 +50,6 @@ public class FeatureSettings extends Panel implements ItemListener, ScrollPane scrollPane; - boolean alignmentHasFeatures = false; - Image linkImage; Scrollbar transparency; @@ -64,9 +62,9 @@ public class FeatureSettings extends Panel implements ItemListener, fr = ap.seqPanel.seqCanvas.getFeatureRenderer(); transparency = new Scrollbar(Scrollbar.HORIZONTAL, - 100 - (int) (fr.transparency * 100), 1, 1, 100); + 100 - (int) (fr.getTransparency() * 100), 1, 1, 100); - if (fr.transparencySetter != null) + if (fr.isTransparencyAvailable()) { transparency.addAdjustmentListener(this); } @@ -81,9 +79,9 @@ public class FeatureSettings extends Panel implements ItemListener, linkImage = java.awt.Toolkit.getDefaultToolkit().getImage(url); } - if (av.featuresDisplayed == null) + if (av.isShowSequenceFeatures() || !fr.hasRenderOrder()) { - fr.findAllFeatures(); + fr.findAllFeatures(true); // was default - now true to make all visible } setTableData(); @@ -91,7 +89,7 @@ public class FeatureSettings extends Panel implements ItemListener, this.setLayout(new BorderLayout()); scrollPane = new ScrollPane(); scrollPane.add(featurePanel); - if (alignmentHasFeatures) + if (fr.getAllFeatureColours()!=null && fr.getAllFeatureColours().size()>0) { add(scrollPane, BorderLayout.CENTER); } @@ -104,7 +102,7 @@ public class FeatureSettings extends Panel implements ItemListener, Panel tPanel = new Panel(new BorderLayout()); - if (fr.transparencySetter != null) + if (fr.isTransparencyAvailable()) { tPanel.add(transparency, BorderLayout.CENTER); tPanel.add(new Label("Transparency"), BorderLayout.EAST); @@ -124,8 +122,8 @@ public class FeatureSettings extends Panel implements ItemListener, { groupPanel .setLayout(new GridLayout( - (fr.featureGroups.size() - fr.hiddenGroups.size()) / 4 + 1, - 4)); + (fr.getFeatureGroupsSize()) / 4 + 1, + 4)); // JBPNote - this was scaled on number of visible groups. seems broken groupPanel.validate(); add(groupPanel, BorderLayout.NORTH); @@ -185,7 +183,7 @@ public class FeatureSettings extends Panel implements ItemListener, public void actionPerformed(ActionEvent e) { - me.sortByScore(new String[] + me.ap.alignFrame.avc.sortAlignmentByFeatureScore(new String[] { type }); } @@ -197,7 +195,7 @@ public class FeatureSettings extends Panel implements ItemListener, public void actionPerformed(ActionEvent e) { - me.sortByDens(new String[] + me.ap.alignFrame.avc.sortAlignmentByFeatureDensity(new String[] { type }); } @@ -253,8 +251,7 @@ public class FeatureSettings extends Panel implements ItemListener, public void setTableData() { - alignmentHasFeatures = fr.buildGroupHash(); - if (alignmentHasFeatures) + if (fr.getAllFeatureColours()!=null && fr.getAllFeatureColours().size()>0) { rebuildGroups(); @@ -279,18 +276,17 @@ public class FeatureSettings extends Panel implements ItemListener, } // TODO: JAL-964 - smoothly incorporate new group entries if panel already // displayed and new groups present - Enumeration gps = fr.featureGroups.keys(); - while (gps.hasMoreElements()) + for (String group:(List)fr.getFeatureGroups()) { - String group = (String) gps.nextElement(); - Boolean vis = (Boolean) fr.featureGroups.get(group); - Checkbox check = new MyCheckbox(group, vis.booleanValue(), + boolean vis = fr.checkGroupVisibility(group, false); + Checkbox check = new MyCheckbox(group, vis, (fr.featureLinks != null && fr.featureLinks .containsKey(group))); check.addMouseListener(this); check.setFont(new Font("Serif", Font.BOLD, 12)); - check.addItemListener(this); - check.setVisible(fr.hiddenGroups.contains(group)); + check.addItemListener(groupItemListener); + // note - visibility seems to correlate with displayed. ???wtf ?? + check.setVisible(vis); groupPanel.add(check); } if (rdrw) @@ -298,7 +294,6 @@ public class FeatureSettings extends Panel implements ItemListener, groupPanel.validate(); } } - // This routine adds and removes checkboxes depending on // Group selection states void resetTable(boolean groupsChanged) @@ -320,8 +315,7 @@ public class FeatureSettings extends Panel implements ItemListener, { group = tmpfeatures[index].featureGroup; - if (group == null || fr.featureGroups.get(group) == null - || ((Boolean) fr.featureGroups.get(group)).booleanValue()) + if (group == null || fr.checkGroupVisibility(group, true)) { type = tmpfeatures[index].getType(); if (!visibleChecks.contains(type)) @@ -350,13 +344,14 @@ public class FeatureSettings extends Panel implements ItemListener, } } - if (fr.renderOrder != null) + if (fr.getRenderOrder() != null) { // First add the checks in the previous render order, // in case the window has been closed and reopened - for (int ro = fr.renderOrder.length - 1; ro > -1; ro--) + List rol = fr.getRenderOrder(); + for (int ro = rol.size() - 1; ro > -1; ro--) { - String item = fr.renderOrder[ro]; + String item = rol.get(ro); if (!visibleChecks.contains(item)) { @@ -418,7 +413,7 @@ public class FeatureSettings extends Panel implements ItemListener, if (addCheck) { boolean selected = false; - if (groupsChanged || av.featuresDisplayed.containsKey(type)) + if (groupsChanged || av.getFeaturesDisplayed().isVisible(type)) { selected = true; } @@ -455,26 +450,22 @@ public class FeatureSettings extends Panel implements ItemListener, selectionChanged(); } - public void itemStateChanged(ItemEvent evt) - { - if (evt != null) - { - // Is the source a top level featureGroup? + private ItemListener groupItemListener = new ItemListener() { + public void itemStateChanged(ItemEvent evt) { Checkbox source = (Checkbox) evt.getSource(); - if (fr.featureGroups.containsKey(source.getLabel())) + fr.setGroupVisibility(source.getLabel(), + source.getState()); + ap.seqPanel.seqCanvas.repaint(); + if (ap.overviewPanel != null) { - fr.featureGroups.put(source.getLabel(), - new Boolean(source.getState())); - ap.seqPanel.seqCanvas.repaint(); - if (ap.overviewPanel != null) - { - ap.overviewPanel.updateOverviewImage(); - } - - resetTable(true); - return; + ap.overviewPanel.updateOverviewImage(); } - } + resetTable(true); + return; + }; + }; + public void itemStateChanged(ItemEvent evt) + { selectionChanged(); } @@ -617,7 +608,7 @@ public class FeatureSettings extends Panel implements ItemListener, MyCheckbox check = (MyCheckbox) evt.getSource(); if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) != 0) { - this.popupSort(check, fr.minmax, evt.getX(), evt.getY()); + this.popupSort(check, fr.getMinMax(), evt.getX(), evt.getY()); } if (fr.featureLinks != null && fr.featureLinks.containsKey(check.type)) { @@ -657,7 +648,7 @@ public class FeatureSettings extends Panel implements ItemListener, public void adjustmentValueChanged(AdjustmentEvent evt) { - fr.transparency = ((float) (100 - transparency.getValue()) / 100f); + fr.setTransparency((float) (100 - transparency.getValue()) / 100f); ap.seqPanel.seqCanvas.repaint(); } @@ -771,81 +762,4 @@ public class FeatureSettings extends Panel implements ItemListener, } } - protected void sortByDens(String[] typ) - { - sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY); - } - - private String[] getDisplayedFeatureTypes() - { - String[] typ = null; - if (fr != null) - { - synchronized (fr.renderOrder) - { - typ = new String[fr.renderOrder.length]; - System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length); - for (int i = 0; i < typ.length; i++) - { - if (av.featuresDisplayed.get(typ[i]) == null) - { - typ[i] = null; - } - } - } - } - return typ; - } - - protected void sortBy(String[] typ, String methodText, final String method) - { - if (typ == null) - { - typ = getDisplayedFeatureTypes(); - } - String gps[] = null; - gps = fr.getGroups(true); - if (typ != null) - { - for (int i = 0; i < typ.length; i++) - { - System.err.println("Sorting on Types:" + typ[i]); - } - } - if (gps != null) - { - - for (int i = 0; i < gps.length; i++) - { - System.err.println("Sorting on groups:" + gps[i]); - } - } - AlignmentPanel alignPanel = ap; - AlignmentI al = alignPanel.av.getAlignment(); - - int start, stop; - SequenceGroup sg = alignPanel.av.getSelectionGroup(); - if (sg != null) - { - start = sg.getStartRes(); - stop = sg.getEndRes(); - } - else - { - start = 0; - stop = al.getWidth(); - } - SequenceI[] oldOrder = al.getSequencesArray(); - AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method); - this.ap.alignFrame.addHistoryItem(new OrderCommand(methodText, - oldOrder, alignPanel.av.getAlignment())); - alignPanel.paintAlignment(true); - - } - - protected void sortByScore(String[] typ) - { - sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE); - } - } diff --git a/src/jalview/appletgui/Finder.java b/src/jalview/appletgui/Finder.java index 6ca6ddf..4796bca 100644 --- a/src/jalview/appletgui/Finder.java +++ b/src/jalview/appletgui/Finder.java @@ -113,7 +113,7 @@ public class Finder extends Panel implements ActionListener features, true, ap)) { ap.alignFrame.sequenceFeatures.setState(true); - av.showSequenceFeatures(true); + av.setShowSequenceFeatures(true); ap.highlightSearchResults(null); } } diff --git a/src/jalview/appletgui/OverviewPanel.java b/src/jalview/appletgui/OverviewPanel.java index 2c2c41a..8486fe0 100755 --- a/src/jalview/appletgui/OverviewPanel.java +++ b/src/jalview/appletgui/OverviewPanel.java @@ -69,7 +69,6 @@ public class OverviewPanel extends Panel implements Runnable, sr.renderGaps = false; sr.forOverview = true; fr = new FeatureRenderer(av); - fr.overview = true; // scale the initial size of overviewpanel to shape of alignment float initialScale = (float) av.getAlignment().getWidth() @@ -229,10 +228,9 @@ public class OverviewPanel extends Panel implements Runnable, return; } - if (av.showSequenceFeatures) + if (av.isShowSequenceFeatures()) { - fr.featureGroups = ap.seqPanel.seqCanvas.getFeatureRenderer().featureGroups; - fr.featureColours = ap.seqPanel.seqCanvas.getFeatureRenderer().featureColours; + fr.transferSettings(ap.seqPanel.seqCanvas.fr); } resizing = true; @@ -260,7 +258,7 @@ public class OverviewPanel extends Panel implements Runnable, int alwidth = av.getAlignment().getWidth(); int alheight = av.getAlignment().getHeight(); - if (av.showSequenceFeatures) + if (av.isShowSequenceFeatures()) { fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer()); } @@ -337,7 +335,7 @@ public class OverviewPanel extends Panel implements Runnable, { color = sr.getResidueBoxColour(seq, lastcol); - if (av.showSequenceFeatures) + if (av.isShowSequenceFeatures()) { color = fr.findFeatureColour(color, seq, lastcol); } diff --git a/src/jalview/appletgui/SeqCanvas.java b/src/jalview/appletgui/SeqCanvas.java index 33caf53..53cca3c 100755 --- a/src/jalview/appletgui/SeqCanvas.java +++ b/src/jalview/appletgui/SeqCanvas.java @@ -589,7 +589,7 @@ public class SeqCanvas extends Panel sr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq), startRes, endRes, offset + ((i - startSeq) * av.charHeight)); - if (av.showSequenceFeatures) + if (av.isShowSequenceFeatures()) { fr.drawSequence(g, nextSeq, startRes, endRes, offset + ((i - startSeq) * av.charHeight)); diff --git a/src/jalview/appletgui/SeqPanel.java b/src/jalview/appletgui/SeqPanel.java index 592fd4f..a95dd27 100644 --- a/src/jalview/appletgui/SeqPanel.java +++ b/src/jalview/appletgui/SeqPanel.java @@ -817,18 +817,14 @@ public class SeqPanel extends Panel implements MouseMotionListener, { for (int i = 0; i < features.length; i++) { - if (av.featuresDisplayed == null - || !av.featuresDisplayed.containsKey(features[i].getType())) + if (av.getFeaturesDisplayed() == null + || !av.getFeaturesDisplayed().isVisible(features[i].getType())) { continue; } if (features[i].featureGroup != null - && seqCanvas.fr.featureGroups != null - && seqCanvas.fr.featureGroups - .containsKey(features[i].featureGroup) - && !((Boolean) seqCanvas.fr.featureGroups - .get(features[i].featureGroup)).booleanValue()) + && !seqCanvas.fr.checkGroupVisibility(features[i].featureGroup,false)) { continue; } diff --git a/src/jalview/appletgui/SequenceRenderer.java b/src/jalview/appletgui/SequenceRenderer.java index 697c0d1..92d5beb 100755 --- a/src/jalview/appletgui/SequenceRenderer.java +++ b/src/jalview/appletgui/SequenceRenderer.java @@ -20,6 +20,7 @@ */ package jalview.appletgui; +import jalview.api.FeatureRenderer; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; @@ -86,6 +87,31 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer return resBoxColour; } + /** + * Get the residue colour at the given sequence position - as determined by + * the sequence group colour (if any), else the colour scheme, possibly + * overridden by a feature colour. + * + * @param seq + * @param position + * @param fr + * @return + */ + @Override + public Color getResidueColour(final SequenceI seq, int position, + FeatureRenderer fr) + { + // TODO replace 8 or so code duplications with calls to this method + // (refactored as needed) + Color col = getResidueBoxColour(seq, position); + + if (fr != null) + { + col = fr.findFeatureColour(col, seq, position); + } + return col; + } + void getBoxColour(ColourSchemeI cs, SequenceI seq, int i) { if (cs != null) diff --git a/src/jalview/appletgui/TreePanel.java b/src/jalview/appletgui/TreePanel.java index b7c766a..655e182 100644 --- a/src/jalview/appletgui/TreePanel.java +++ b/src/jalview/appletgui/TreePanel.java @@ -20,14 +20,29 @@ */ package jalview.appletgui; -import java.awt.*; -import java.awt.event.*; - -import jalview.analysis.*; -import jalview.datamodel.*; -import jalview.io.*; +import jalview.analysis.NJTree; +import jalview.api.analysis.ScoreModelI; +import jalview.api.analysis.ViewBasedAnalysisI; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentView; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.SequenceI; +import jalview.io.NewickFile; +import jalview.schemes.ResidueProperties; import jalview.util.MessageManager; +import java.awt.BorderLayout; +import java.awt.CheckboxMenuItem; +import java.awt.Color; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.ScrollPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + public class TreePanel extends EmbmenuFrame implements ActionListener, ItemListener { @@ -204,8 +219,8 @@ public class TreePanel extends EmbmenuFrame implements ActionListener, { int start, end; SequenceI[] seqs; - boolean selview = (av.getSelectionGroup() != null) - && (av.getSelectionGroup().getSize() > 1); + boolean selview = av.getSelectionGroup() != null + && av.getSelectionGroup().getSize() > 1; AlignmentView seqStrings = av.getAlignmentView(selview); if (!selview) { @@ -220,8 +235,27 @@ public class TreePanel extends EmbmenuFrame implements ActionListener, seqs = av.getSelectionGroup().getSequencesInOrder( av.getAlignment()); } - - tree = new NJTree(seqs, seqStrings, type, pwtype, start, end); + ScoreModelI sm = ResidueProperties.getScoreModel(pwtype); + if (sm instanceof ViewBasedAnalysisI) + { + try + { + sm = sm.getClass().newInstance(); + ((ViewBasedAnalysisI) sm) + .configureFromAlignmentView(treeCanvas.ap); + } catch (Exception q) + { + System.err.println("Couldn't create a scoremodel instance for " + + sm.getName()); + q.printStackTrace(); + } + tree = new NJTree(seqs, seqStrings, type, pwtype, sm, start, end); + } + else + { + tree = new NJTree(seqs, seqStrings, type, pwtype, null, start, + end); + } } tree.reCount(tree.getTopNode()); diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java index 3b0a23e..3dea84e 100755 --- a/src/jalview/bin/Cache.java +++ b/src/jalview/bin/Cache.java @@ -379,15 +379,21 @@ public class Cache String jnlpVersion = System.getProperty("jalview.version"); String codeVersion = getProperty("VERSION"); - + String codeInstallation = getProperty("INSTALLATION"); if (codeVersion == null) { // THIS SHOULD ONLY BE THE CASE WHEN TESTING!! codeVersion = "Test"; jnlpVersion = "Test"; + codeInstallation = ""; + } + else + { + codeInstallation = " (" + codeInstallation + ")"; } - System.out.println("Jalview Version: " + codeVersion); + System.out + .println("Jalview Version: " + codeVersion + codeInstallation); // jnlpVersion will be null if we're using InstallAnywhere // Dont do this check if running in headless mode @@ -477,6 +483,8 @@ public class Cache applicationProperties.remove("AUTHORS"); applicationProperties.remove("AUTHORFNAMES"); applicationProperties.remove("YEAR"); + applicationProperties.remove("BUILD_DATE"); + applicationProperties.remove("INSTALLATION"); } /** diff --git a/src/jalview/bin/Jalview.java b/src/jalview/bin/Jalview.java index e5a22e0..50e3559 100755 --- a/src/jalview/bin/Jalview.java +++ b/src/jalview/bin/Jalview.java @@ -80,11 +80,6 @@ public class Jalview } /** - * Put protein=true for get a protein example - */ - private static boolean protein = false; - - /** * main class for Jalview application * * @param args @@ -403,6 +398,10 @@ public class Jalview { af.getViewport().setSortByTree(true); } + if (aparser.contains("no-annotation")) + { + af.getViewport().setShowAnnotation(false); + } if (aparser.contains("nosortbytree")) { af.getViewport().setSortByTree(false); @@ -536,8 +535,7 @@ public class Jalview // //////////////////// if (!headless && file == null && vamsasImport == null - && jalview.bin.Cache.getDefault("SHOW_STARTUP_FILE", true) - && protein == true) + && jalview.bin.Cache.getDefault("SHOW_STARTUP_FILE", true)) { file = jalview.bin.Cache.getDefault( "STARTUP_FILE", @@ -669,7 +667,7 @@ public class Jalview public void run() { Cache.log - .info("Initialising googletracker for usage stats."); + .debug("Initialising googletracker for usage stats."); Cache.initGoogleTracker(); Cache.log.debug("Tracking enabled."); } @@ -677,7 +675,7 @@ public class Jalview { public void run() { - Cache.log.info("Not enabling Google Tracking."); + Cache.log.debug("Not enabling Google Tracking."); } }, null, true); desktop.addDialogThread(prompter); diff --git a/src/jalview/bin/JalviewLite.java b/src/jalview/bin/JalviewLite.java index ae8bc98..833dd7e 100644 --- a/src/jalview/bin/JalviewLite.java +++ b/src/jalview/bin/JalviewLite.java @@ -1990,7 +1990,7 @@ public class JalviewLite extends Applet implements param = applet.getParameter("showFeatureSettings"); if (param != null && param.equalsIgnoreCase("true")) { - newAlignFrame.viewport.showSequenceFeatures(true); + newAlignFrame.viewport.setShowSequenceFeatures(true); new FeatureSettings(newAlignFrame.alignPanel); } diff --git a/src/jalview/controller/AlignViewController.java b/src/jalview/controller/AlignViewController.java index dbc3524..21cf630 100644 --- a/src/jalview/controller/AlignViewController.java +++ b/src/jalview/controller/AlignViewController.java @@ -21,15 +21,18 @@ package jalview.controller; import java.awt.Color; +import java.util.ArrayList; import java.util.BitSet; import java.util.List; +import jalview.analysis.AlignmentSorter; import jalview.api.AlignViewControllerGuiI; import jalview.api.AlignViewControllerI; import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; +import jalview.api.FeatureRenderer; +import jalview.commands.OrderCommand; import jalview.datamodel.AlignmentI; -import jalview.datamodel.AnnotatedCollectionI; import jalview.datamodel.ColumnSelection; import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceFeature; @@ -296,4 +299,74 @@ public class AlignViewController implements AlignViewControllerI return false; } } + + @Override + public void sortAlignmentByFeatureDensity(String[] typ) + { + sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY); + } + + protected void sortBy(String[] typ, String methodText, final String method) + { + FeatureRenderer fr = alignPanel.getFeatureRenderer(); + if (typ == null) + { + typ = fr==null ? null : fr.getDisplayedFeatureTypes(); + } + String gps[] = null; + gps = fr==null ? null : fr.getDisplayedFeatureGroups(); + if (typ != null) + { + ArrayList types = new ArrayList(); + for (int i = 0; i < typ.length; i++) + { + if (typ[i] != null) + { + types.add(typ[i]); + } + typ = new String[types.size()]; + types.toArray(typ); + } + } + if (gps != null) + { + ArrayList grps = new ArrayList(); + + for (int i = 0; i < gps.length; i++) + { + if (gps[i] != null) + { + grps.add(gps[i]); + } + } + gps = new String[grps.size()]; + grps.toArray(gps); + } + AlignmentI al = viewport.getAlignment(); + + int start, stop; + SequenceGroup sg = viewport.getSelectionGroup(); + if (sg != null) + { + start = sg.getStartRes(); + stop = sg.getEndRes(); + } + else + { + start = 0; + stop = al.getWidth(); + } + SequenceI[] oldOrder = al.getSequencesArray(); + AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method); + avcg.addHistoryItem(new OrderCommand(methodText, oldOrder, viewport + .getAlignment())); + alignPanel.paintAlignment(true); + + } + + @Override + public void sortAlignmentByFeatureScore(String[] typ) + { + sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE); + } } diff --git a/src/jalview/controller/FeatureSettingsController.java b/src/jalview/controller/FeatureSettingsController.java new file mode 100644 index 0000000..ebf4958 --- /dev/null +++ b/src/jalview/controller/FeatureSettingsController.java @@ -0,0 +1,12 @@ +package jalview.controller; + +import jalview.api.FeatureRenderer; +import jalview.api.FeatureSettingsModelI; + +public class FeatureSettingsController implements jalview.api.FeatureSettingsControllerI +{ + FeatureSettingsControllerGuiI settingUI; + FeatureRenderer fr; + FeatureSettingsModelI fsettings; + +} diff --git a/src/jalview/controller/FeatureSettingsControllerGuiI.java b/src/jalview/controller/FeatureSettingsControllerGuiI.java new file mode 100644 index 0000000..781759e --- /dev/null +++ b/src/jalview/controller/FeatureSettingsControllerGuiI.java @@ -0,0 +1,6 @@ +package jalview.controller; + +public interface FeatureSettingsControllerGuiI +{ + +} diff --git a/src/jalview/datamodel/Alignment.java b/src/jalview/datamodel/Alignment.java index 4057773..9c5914f 100755 --- a/src/jalview/datamodel/Alignment.java +++ b/src/jalview/datamodel/Alignment.java @@ -1489,6 +1489,27 @@ public class Alignment implements AlignmentI return aa; } + /** + * Returns an iterable collection of any annotations that match on given + * sequence ref, calcId and label (ignoring null values). + */ + @Override + public Iterable findAnnotations(SequenceI seq, + String calcId, String label) + { + ArrayList aa = new ArrayList(); + for (AlignmentAnnotation ann : getAlignmentAnnotation()) + { + if (ann.getCalcId() != null && ann.getCalcId().equals(calcId) + && ann.sequenceRef != null && ann.sequenceRef == seq + && ann.label != null && ann.label.equals(label)) + { + aa.add(ann); + } + } + return aa; + } + @Override public void moveSelectedSequencesByOne(SequenceGroup sg, Map map, boolean up) diff --git a/src/jalview/datamodel/AnnotatedCollectionI.java b/src/jalview/datamodel/AnnotatedCollectionI.java index 0b4c117..6814b7e 100644 --- a/src/jalview/datamodel/AnnotatedCollectionI.java +++ b/src/jalview/datamodel/AnnotatedCollectionI.java @@ -33,6 +33,9 @@ public interface AnnotatedCollectionI extends SequenceCollectionI Iterable findAnnotation(String calcId); + Iterable findAnnotations(SequenceI seq, + String calcId, String label); + /** * context for this annotated collection * diff --git a/src/jalview/datamodel/Sequence.java b/src/jalview/datamodel/Sequence.java index 69d6da2..0652fb5 100755 --- a/src/jalview/datamodel/Sequence.java +++ b/src/jalview/datamodel/Sequence.java @@ -879,22 +879,30 @@ public class Sequence implements SequenceI return datasetSequence; } + /** + * Returns a new array containing this sequence's annotations, or null. + */ public AlignmentAnnotation[] getAnnotation() { - if (annotation == null) - { - return null; - } - - AlignmentAnnotation[] ret = new AlignmentAnnotation[annotation.size()]; - for (int r = 0; r < ret.length; r++) - { - ret[r] = annotation.elementAt(r); - } + return annotation == null ? null : annotation + .toArray(new AlignmentAnnotation[annotation.size()]); + } - return ret; + /** + * Returns true if this sequence has the given annotation (by object + * identity). + */ + @Override + public boolean hasAnnotation(AlignmentAnnotation ann) + { + return annotation == null ? false : annotation.contains(ann); } + /** + * Add the given annotation, if not already added, and set its sequence ref to + * be this sequence. Does nothing if this sequence's annotations already + * include this annotation (by identical object reference). + */ public void addAlignmentAnnotation(AlignmentAnnotation annotation) { if (this.annotation == null) diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java index 17348c2..752c6d4 100755 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@ -178,7 +178,9 @@ public class SequenceGroup implements AnnotatedCollectionI endRes = seqsel.endRes; cs = seqsel.cs; if (seqsel.description != null) + { description = new String(seqsel.description); + } hidecols = seqsel.hidecols; hidereps = seqsel.hidereps; idColour = seqsel.idColour; @@ -238,7 +240,9 @@ public class SequenceGroup implements AnnotatedCollectionI } } if (!found) + { continue; + } } AlignmentAnnotation newannot = new AlignmentAnnotation( seq.getAnnotation()[a]); @@ -1261,6 +1265,29 @@ public class SequenceGroup implements AnnotatedCollectionI } /** + * Returns a list of annotations that match the specified sequenceRef, calcId + * and label, ignoring null values. + * + * @return list of AlignmentAnnotation objects + */ + @Override + public Iterable findAnnotations(SequenceI seq, + String calcId, String label) + { + ArrayList aa = new ArrayList(); + for (AlignmentAnnotation ann : getAlignmentAnnotation()) + { + if (ann.getCalcId() != null && ann.getCalcId().equals(calcId) + && ann.sequenceRef != null && ann.sequenceRef == seq + && ann.label != null && ann.label.equals(label)) + { + aa.add(ann); + } + } + return aa; + } + + /** * Answer true if any annotation matches the calcId passed in (if not null). * * @param calcId diff --git a/src/jalview/datamodel/SequenceI.java b/src/jalview/datamodel/SequenceI.java index 8376047..fc67efd 100755 --- a/src/jalview/datamodel/SequenceI.java +++ b/src/jalview/datamodel/SequenceI.java @@ -317,6 +317,8 @@ public interface SequenceI public AlignmentAnnotation[] getAnnotation(); + public boolean hasAnnotation(AlignmentAnnotation ann); + public void addAlignmentAnnotation(AlignmentAnnotation annotation); public void removeAlignmentAnnotation(AlignmentAnnotation annotation); diff --git a/src/jalview/exceptions/JalviewException.java b/src/jalview/exceptions/JalviewException.java new file mode 100644 index 0000000..80e0b08 --- /dev/null +++ b/src/jalview/exceptions/JalviewException.java @@ -0,0 +1,25 @@ +package jalview.exceptions; + +@SuppressWarnings("serial") +public class JalviewException extends Exception +{ + public JalviewException(String exceptionMessage) + { + super(exceptionMessage); + } + + public JalviewException() + { + super(); + } + + public JalviewException(String exceptionMessage, Throwable cause) + { + super(exceptionMessage, cause); + } + + public JalviewException(Throwable cause) + { + super(cause); + } +} diff --git a/src/jalview/exceptions/NoFileSelectedException.java b/src/jalview/exceptions/NoFileSelectedException.java new file mode 100644 index 0000000..5c56f47 --- /dev/null +++ b/src/jalview/exceptions/NoFileSelectedException.java @@ -0,0 +1,10 @@ +package jalview.exceptions; + +@SuppressWarnings("serial") +public class NoFileSelectedException extends JalviewException +{ + public NoFileSelectedException(String msg) + { + super(msg); + } +} diff --git a/src/jalview/ext/jmol/PDBFileWithJmol.java b/src/jalview/ext/jmol/PDBFileWithJmol.java index f5710d3..92dce36 100644 --- a/src/jalview/ext/jmol/PDBFileWithJmol.java +++ b/src/jalview/ext/jmol/PDBFileWithJmol.java @@ -188,7 +188,10 @@ public class PDBFileWithJmol extends AlignFile implements { String mt = model.getModelTitle() == null ? getDataName() : model.getModelTitle(); - mt += _lastChainId; + if (_lastChainId >= ' ') + { + mt += _lastChainId; + } AlignmentAnnotation ann = new AlignmentAnnotation( "Secondary Structure", "Secondary Structure for " + mt, asecstr); diff --git a/src/jalview/ext/rbvi/chimera/ChimeraCommands.java b/src/jalview/ext/rbvi/chimera/ChimeraCommands.java index d3c8c09..4afc526 100644 --- a/src/jalview/ext/rbvi/chimera/ChimeraCommands.java +++ b/src/jalview/ext/rbvi/chimera/ChimeraCommands.java @@ -22,17 +22,20 @@ package jalview.ext.rbvi.chimera; import jalview.api.FeatureRenderer; import jalview.api.SequenceRenderer; -import jalview.api.structures.JalviewStructureDisplayI; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; import jalview.structure.StructureMapping; import jalview.structure.StructureMappingcommandSet; import jalview.structure.StructureSelectionManager; -import jalview.util.Format; +import jalview.util.ColorUtils; +import jalview.util.Comparison; import java.awt.Color; import java.util.ArrayList; -import java.util.Hashtable; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; /** * Routines for generating Chimera commands for Jalview/Chimera binding @@ -55,104 +58,233 @@ public class ChimeraCommands SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr, AlignmentI alignment) { + Map>>> colourMap = buildColoursMap( + ssm, files, sequence, sr, fr, alignment); - ArrayList cset = new ArrayList(); - Hashtable colranges=new Hashtable(); + List colourCommands = buildColourCommands(colourMap); + + StructureMappingcommandSet cs = new StructureMappingcommandSet( + ChimeraCommands.class, null, + colourCommands.toArray(new String[0])); + + return new StructureMappingcommandSet[] + { cs }; + } + + /** + * Traverse the map of colours/models/chains/positions to construct a list of + * 'color' commands (one per distinct colour used). The format of each command + * is + * + *
    color colorname #modelnumber:range.chain e.g. color #00ff00 + * #0:2.B,4.B,9-12.B|#1:1.A,2-6.A,... + * + * @see http + * ://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/midas/frameatom_spec + * .html + * + * @param colourMap + * @return + */ + protected static List buildColourCommands( + Map>>> colourMap) + { + /* + * This version concatenates all commands into a single String (semi-colon + * delimited). If length limit issues arise, refactor to return one color + * command per colour. + */ + List commands = new ArrayList(); + StringBuilder sb = new StringBuilder(256); + boolean firstColour = true; + for (Color colour : colourMap.keySet()) + { + String colourCode = ColorUtils.toTkCode(colour); + if (!firstColour) + { + sb.append("; "); + } + sb.append("color ").append(colourCode).append(" "); + firstColour = false; + boolean firstModelForColour = true; + final Map>> colourData = colourMap.get(colour); + for (Integer model : colourData.keySet()) + { + boolean firstPositionForModel = true; + if (!firstModelForColour) + { + sb.append("|"); + } + firstModelForColour = false; + sb.append("#").append(model).append(":"); + + final Map> modelData = colourData.get(model); + for (String chain : modelData.keySet()) + { + for (int[] range : modelData.get(chain)) + { + if (!firstPositionForModel) + { + sb.append(","); + } + if (range[0] == range[1]) + { + sb.append(range[0]); + } + else + { + sb.append(range[0]).append("-").append(range[1]); + } + sb.append(".").append(chain); + firstPositionForModel = false; + } + } + } + } + commands.add(sb.toString()); + return commands; + } + + /** + *
    +   * Build a data structure which maps contiguous subsequences for each colour. 
    +   * This generates a data structure from which we can easily generate the 
    +   * Chimera command for colour by sequence.
    +   * Color
    +   *     Model number
    +   *         Chain
    +   *             list of start/end ranges
    +   * Ordering is by order of addition (for colours and positions), natural ordering (for models and chains)
    +   * 
    + */ + protected static Map>>> buildColoursMap( + StructureSelectionManager ssm, String[] files, + SequenceI[][] sequence, SequenceRenderer sr, FeatureRenderer fr, + AlignmentI alignment) + { + Map>>> colourMap = new LinkedHashMap>>>(); + Color lastColour = null; for (int pdbfnum = 0; pdbfnum < files.length; pdbfnum++) { - float cols[] = new float[4]; StructureMapping[] mapping = ssm.getMapping(files[pdbfnum]); - StringBuffer command = new StringBuffer(); - StructureMappingcommandSet smc; - ArrayList str = new ArrayList(); if (mapping == null || mapping.length < 1) + { continue; + } - int startPos = -1, lastPos = -1, startModel = -1, lastModel = -1; - String startChain = "", lastChain = ""; - Color lastCol = null; + int startPos = -1, lastPos = -1; + String lastChain = ""; for (int s = 0; s < sequence[pdbfnum].length; s++) { for (int sp, m = 0; m < mapping.length; m++) { - if (mapping[m].getSequence() == sequence[pdbfnum][s] - && (sp = alignment.findIndex(sequence[pdbfnum][s])) > -1) + final SequenceI seq = sequence[pdbfnum][s]; + if (mapping[m].getSequence() == seq + && (sp = alignment.findIndex(seq)) > -1) { SequenceI asp = alignment.getSequenceAt(sp); for (int r = 0; r < asp.getLength(); r++) { // no mapping to gaps in sequence - if (jalview.util.Comparison.isGap(asp.getCharAt(r))) + if (Comparison.isGap(asp.getCharAt(r))) { continue; } int pos = mapping[m].getPDBResNum(asp.findPosition(r)); if (pos < 1 || pos == lastPos) + { continue; + } - Color col = sr.getResidueBoxColour(sequence[pdbfnum][s], r); + Color colour = sr.getResidueColour(seq, r, fr); + final String chain = mapping[m].getChain(); - if (fr != null) - col = fr.findFeatureColour(col, sequence[pdbfnum][s], r); - if (lastCol != col || lastPos + 1 != pos - || pdbfnum != lastModel - || !mapping[m].getChain().equals(lastChain)) + /* + * Just keep incrementing the end position for this colour range + * _unless_ colour, PDB model or chain has changed, or there is a + * gap in the mapped residue sequence + */ + final boolean newColour = !colour.equals(lastColour); + final boolean nonContig = lastPos + 1 != pos; + final boolean newChain = !chain.equals(lastChain); + if (newColour || nonContig || newChain) { - if (lastCol != null) + if (startPos != -1) { - addColourRange(colranges, lastCol,startModel,startPos,lastPos,lastChain); + addColourRange(colourMap, lastColour, pdbfnum, startPos, + lastPos, lastChain); } - lastCol = null; startPos = pos; - startModel = pdbfnum; - startChain = mapping[m].getChain(); } - lastCol = col; + lastColour = colour; lastPos = pos; - lastModel = pdbfnum; - lastChain = mapping[m].getChain(); + lastChain = chain; } // final colour range - if (lastCol != null) + if (lastColour != null) { - addColourRange(colranges, lastCol,startModel,startPos,lastPos,lastChain); + addColourRange(colourMap, lastColour, pdbfnum, startPos, + lastPos, lastChain); } break; } } } - // Finally, add the command set ready to be returned. - StringBuffer coms=new StringBuffer(); - for (String cr:colranges.keySet()) - { - coms.append("color #"+cr+" "+colranges.get(cr)+";"); - } - cset.add(new StructureMappingcommandSet(ChimeraCommands.class, - files[pdbfnum], new String[] { coms.toString() })); } - return cset.toArray(new StructureMappingcommandSet[cset.size()]); + return colourMap; } - private static void addColourRange(Hashtable colranges, Color lastCol, int startModel, - int startPos, int lastPos, String lastChain) + /** + * Helper method to add one contiguous colour range to the colour map. + * + * @param colourMap + * @param colour + * @param model + * @param startPos + * @param endPos + * @param chain + */ + protected static void addColourRange( + Map>>> colourMap, + Color colour, int model, int startPos, int endPos, String chain) { - - String colstring = ((lastCol.getRed()< 16) ? "0":"")+Integer.toHexString(lastCol.getRed()) - + ((lastCol.getGreen()< 16) ? "0":"")+Integer.toHexString(lastCol.getGreen()) - + ((lastCol.getBlue()< 16) ? "0":"")+Integer.toHexString(lastCol.getBlue()); - StringBuffer currange = colranges.get(colstring); - if (currange==null) + /* + * Get/initialize map of data for the colour + */ + Map>> colourData = colourMap + .get(colour); + if (colourData == null) + { + colourMap + .put(colour, + colourData = new TreeMap>>()); + } + + /* + * Get/initialize map of data for the colour and model + */ + Map> modelData = colourData.get(model); + if (modelData == null) { - colranges.put(colstring,currange = new StringBuffer()); + colourData.put(model, modelData = new TreeMap>()); } - if (currange.length()>0) + + /* + * Get/initialize map of data for colour, model and chain + */ + List chainData = modelData.get(chain); + if (chainData == null) { - currange.append("|"); + modelData.put(chain, chainData = new ArrayList()); } - currange.append("#" + startModel + ":" + ((startPos==lastPos) ? startPos : startPos + "-" - + lastPos) + "." + lastChain); + + /* + * Add the start/end positions + */ + chainData.add(new int[] + { startPos, endPos }); } } diff --git a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java index fb03f04..b5bfbaa 100644 --- a/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java +++ b/src/jalview/ext/rbvi/chimera/JalviewChimeraBinding.java @@ -58,6 +58,9 @@ public abstract class JalviewChimeraBinding extends SequenceStructureBinding, StructureSelectionManagerProvider { + + private static final boolean debug = false; + private static final String PHOSPHORUS = "P"; private static final String ALPHACARBON = "CA"; @@ -654,10 +657,12 @@ public abstract class JalviewChimeraBinding extends } if (selectioncom.length() > 0) { - // TODO remove debug output - System.out.println("Select regions:\n" + selectioncom.toString()); - System.out - .println("Superimpose command(s):\n" + command.toString()); + if (debug) + { + System.out.println("Select regions:\n" + selectioncom.toString()); + System.out.println("Superimpose command(s):\n" + + command.toString()); + } allComs.append("~display all; chain @CA|P; ribbon " + selectioncom.toString() + ";"+command.toString()); // selcom.append("; ribbons; "); @@ -669,7 +674,10 @@ public abstract class JalviewChimeraBinding extends { selectioncom.setLength(selectioncom.length() - 1); } - System.out.println("Select regions:\n" + selectioncom.toString()); + if (debug) + { + System.out.println("Select regions:\n" + selectioncom.toString()); + } allComs.append("; ~display all; chain @CA|P; ribbon " + selectioncom.toString() + "; focus"); // evalStateCommand("select *; backbone; select "+selcom.toString()+"; cartoons; center "+selcom.toString()); @@ -782,7 +790,7 @@ public abstract class JalviewChimeraBinding extends private void waitForChimera() { - while (viewer.isBusy()) + while (viewer != null && viewer.isBusy()) { try { Thread.sleep(15); @@ -954,8 +962,6 @@ public abstract class JalviewChimeraBinding extends } } - boolean debug = true; - private void log(String message) { System.err.println("## Chimera log: " + message); @@ -963,8 +969,8 @@ public abstract class JalviewChimeraBinding extends private void viewerCommandHistory(boolean enable) { - log("(Not yet implemented) History " - + ((debug || enable) ? "on" : "off")); + // log("(Not yet implemented) History " + // + ((debug || enable) ? "on" : "off")); } public void loadInline(String string) diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 42460dc..015b95b 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -30,6 +30,7 @@ import jalview.analysis.ParseProperties; import jalview.analysis.SequenceIdMatcher; import jalview.api.AlignViewControllerGuiI; import jalview.api.AlignViewControllerI; +import jalview.api.AlignmentViewPanel; import jalview.api.analysis.ScoreModelI; import jalview.bin.Cache; import jalview.commands.CommandI; @@ -54,6 +55,7 @@ import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.io.AlignmentProperties; import jalview.io.AnnotationFile; +import jalview.io.BioJsHTMLOutput; import jalview.io.FeaturesFile; import jalview.io.FileLoader; import jalview.io.FormatAdapter; @@ -115,6 +117,7 @@ import java.beans.PropertyChangeEvent; import java.io.File; import java.net.URL; import java.util.ArrayList; +import java.util.Arrays; import java.util.Enumeration; import java.util.Hashtable; import java.util.List; @@ -765,7 +768,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, setColourSelected(ColourSchemeProperty.getColourName(av .getGlobalColourScheme())); - showSeqFeatures.setSelected(av.showSequenceFeatures); + showSeqFeatures.setSelected(av.isShowSequenceFeatures()); hiddenMarkers.setState(av.showHiddenMarkers); applyToAllGroups.setState(av.getColourAppliesToAllGroups()); showNpFeatsMenuitem.setSelected(av.isShowNpFeats()); @@ -1233,6 +1236,12 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, new HtmlSvgOutput(null, alignPanel); } + @Override + public void bioJSMenuItem_actionPerformed(ActionEvent e) + { + new BioJsHTMLOutput(alignPanel, + alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()); + } public void createImageMap(File file, String image) { alignPanel.makePNGImageMap(file, image); @@ -3083,7 +3092,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, { viewport.setShowSequenceFeaturesHeight(showSeqFeaturesHeight .isSelected()); - if (viewport.getShowSequenceFeaturesHeight()) + if (viewport.isShowSequenceFeaturesHeight()) { // ensure we're actually displaying features viewport.setShowSequenceFeatures(true); @@ -4188,28 +4197,17 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, else if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize() == 1) { - int option = JOptionPane - .showConfirmDialog( -this, - "More than one sequece group selection is required for this Job, click \n'Cancel' to edit your selection or 'Ok' to submit the entire sequence.", - "Invalid selection", - JOptionPane.OK_CANCEL_OPTION); + int option = JOptionPane.showConfirmDialog(this, + MessageManager.getString("warn.oneseq_msainput_selection"), + MessageManager.getString("label.invalid_selection"), + JOptionPane.OK_CANCEL_OPTION); if (option == JOptionPane.OK_OPTION) { msa = viewport.getAlignmentView(false); } - } else { - /* - * Vector seqs = viewport.getAlignment().getSequences(); - * - * if (seqs.size() > 1) { msa = new SequenceI[seqs.size()]; - * - * for (int i = 0; i < seqs.size(); i++) { msa[i] = (SequenceI) - * seqs.elementAt(i); } } - */ msa = viewport.getAlignmentView(false); } return msa; @@ -4884,7 +4882,7 @@ this, { featuresFile = new FeaturesFile(file, type).parse(viewport .getAlignment().getDataset(), alignPanel.getSeqPanel().seqCanvas - .getFeatureRenderer().featureColours, false, + .getFeatureRenderer().getFeatureColours(), false, jalview.bin.Cache.getDefault("RELAXEDSEQIDMATCHING", false)); } catch (Exception ex) { @@ -4893,7 +4891,7 @@ this, if (featuresFile) { - viewport.showSequenceFeatures = true; + viewport.setShowSequenceFeatures(true); showSeqFeatures.setSelected(true); if (alignPanel.getSeqPanel().seqCanvas.fr != null) { @@ -5832,6 +5830,15 @@ this, .setShowAutocalculatedAbove(isShowAutoCalculatedAbove()); alignPanel.paintAlignment(true); } + + /** + * + * @return alignment panels in this alignemnt frame + */ + public List getAlignPanels() + { + return alignPanels == null ? Arrays.asList(alignPanel) : alignPanels; + } } class PrintThread extends Thread diff --git a/src/jalview/gui/AlignViewport.java b/src/jalview/gui/AlignViewport.java index 40f95e2..38f0ea1 100644 --- a/src/jalview/gui/AlignViewport.java +++ b/src/jalview/gui/AlignViewport.java @@ -95,10 +95,6 @@ public class AlignViewport extends AlignmentViewport implements boolean renderGaps = true; - boolean showSequenceFeatures = false; - - private boolean showAnnotation = true; - SequenceAnnotationOrder sortAnnotationsBy = null; int charHeight; @@ -125,12 +121,6 @@ public class AlignViewport extends AlignmentViewport implements boolean cursorMode = false; - /** - * Keys are the feature types which are currently visible. Note: Values are - * not used! - */ - Hashtable featuresDisplayed = null; - boolean antiAlias = false; Rectangle explodedPosition; @@ -148,9 +138,6 @@ public class AlignViewport extends AlignmentViewport implements Color textColour = Color.black; Color textColour2 = Color.white; - - private boolean rightAlignIds = false; - /** * Creates a new AlignViewport object. * @@ -368,22 +355,6 @@ public class AlignViewport extends AlignmentViewport implements } /** - * set the flag - * - * @param b - * features are displayed if true - */ - public void setShowSequenceFeatures(boolean b) - { - showSequenceFeatures = b; - } - - public boolean getShowSequenceFeatures() - { - return showSequenceFeatures; - } - - /** * centre columnar annotation labels in displayed alignment annotation TODO: * add to jalviewXML and annotation display settings */ @@ -837,27 +808,6 @@ public class AlignViewport extends AlignmentViewport implements * * @return DOCUMENT ME! */ - public boolean getShowAnnotation() - { - return isShowAnnotation(); - } - - /** - * DOCUMENT ME! - * - * @param b - * DOCUMENT ME! - */ - public void setShowAnnotation(boolean b) - { - showAnnotation = b; - } - - /** - * DOCUMENT ME! - * - * @return DOCUMENT ME! - */ public boolean getScaleAboveWrapped() { return scaleAboveWrapped; @@ -1101,8 +1051,6 @@ public class AlignViewport extends AlignmentViewport implements return followSelection; } - boolean showSeqFeaturesHeight; - public void sendSelection() { jalview.structure.StructureSelectionManager @@ -1111,16 +1059,6 @@ public class AlignViewport extends AlignmentViewport implements new ColumnSelection(getColumnSelection()), this); } - public void setShowSequenceFeaturesHeight(boolean selected) - { - showSeqFeaturesHeight = selected; - } - - public boolean getShowSequenceFeaturesHeight() - { - return showSeqFeaturesHeight; - } - /** * return the alignPanel containing the given viewport. Use this to get the * components currently handling the given viewport. @@ -1293,19 +1231,4 @@ public class AlignViewport extends AlignmentViewport implements { this.showAutocalculatedAbove = showAutocalculatedAbove; } - - public boolean isShowAnnotation() - { - return showAnnotation; - } - - public boolean isRightAlignIds() - { - return rightAlignIds; - } - - public void setRightAlignIds(boolean rightAlignIds) - { - this.rightAlignIds = rightAlignIds; - } } diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index e4a4c90..e859fb1 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -1513,11 +1513,8 @@ public class AlignmentPanel extends GAlignmentPanel implements return av.getAlignment(); } - /** - * get the name for this view - * - * @return - */ + + @Override public String getViewName() { return av.viewName; @@ -1556,18 +1553,23 @@ public class AlignmentPanel extends GAlignmentPanel implements new OOMWarning(string, error, this); } - public FeatureRenderer cloneFeatureRenderer() + @Override + public jalview.api.FeatureRenderer cloneFeatureRenderer() { return new FeatureRenderer(this); } - - public void updateFeatureRenderer(FeatureRenderer fr) + @Override + public jalview.api.FeatureRenderer getFeatureRenderer() + { + return seqPanel.seqCanvas.getFeatureRenderer(); + } + public void updateFeatureRenderer(jalview.renderer.seqfeatures.FeatureRenderer fr) { fr.transferSettings(getSeqPanel().seqCanvas.getFeatureRenderer()); } - public void updateFeatureRendererFrom(FeatureRenderer fr) + public void updateFeatureRendererFrom(jalview.api.FeatureRenderer fr) { if (getSeqPanel().seqCanvas.getFeatureRenderer() != null) { diff --git a/src/jalview/gui/AnnotationExporter.java b/src/jalview/gui/AnnotationExporter.java index c68b2b1..e43c06b 100644 --- a/src/jalview/gui/AnnotationExporter.java +++ b/src/jalview/gui/AnnotationExporter.java @@ -20,16 +20,31 @@ */ package jalview.gui; -import java.util.*; -import java.util.List; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.SequenceGroup; +import jalview.io.AnnotationFile; +import jalview.io.FeaturesFile; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; +import jalview.util.MessageManager; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Hashtable; +import java.util.List; -import jalview.datamodel.*; -import jalview.io.*; -import jalview.util.MessageManager; +import javax.swing.BorderFactory; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.SwingConstants; /** * @@ -112,14 +127,16 @@ public class AnnotationExporter extends JPanel if (GFFFormat.isSelected()) { text = new FeaturesFile().printGFFFormat(ap.av.getAlignment() - .getDataset().getSequencesArray(), - getDisplayedFeatureCols(), true, ap.av.isShowNpFeats());// ap.av.featuresDisplayed//); + .getDataset().getSequencesArray(), ap + .getFeatureRenderer().getDisplayedFeatureCols(), true, + ap.av.isShowNpFeats());// ap.av.featuresDisplayed//); } else { text = new FeaturesFile().printJalviewFormat(ap.av.getAlignment() - .getDataset().getSequencesArray(), - getDisplayedFeatureCols(), true, ap.av.isShowNpFeats()); // ap.av.featuresDisplayed); + .getDataset().getSequencesArray(), ap + .getFeatureRenderer().getDisplayedFeatureCols(), true, + ap.av.isShowNpFeats()); // ap.av.featuresDisplayed); } } else @@ -159,14 +176,14 @@ public class AnnotationExporter extends JPanel if (GFFFormat.isSelected()) { text = new FeaturesFile().printGFFFormat(ap.av.getAlignment() - .getDataset().getSequencesArray(), - getDisplayedFeatureCols(), true, ap.av.isShowNpFeats()); + .getDataset().getSequencesArray(), ap.getFeatureRenderer() + .getDisplayedFeatureCols(), true, ap.av.isShowNpFeats()); } else { text = new FeaturesFile().printJalviewFormat(ap.av.getAlignment() - .getDataset().getSequencesArray(), - getDisplayedFeatureCols(), true, ap.av.isShowNpFeats()); + .getDataset().getSequencesArray(), ap.getFeatureRenderer() + .getDisplayedFeatureCols(), true, ap.av.isShowNpFeats()); } } else if (!features) @@ -206,27 +223,6 @@ public class AnnotationExporter extends JPanel close_actionPerformed(null); } - - private Hashtable getDisplayedFeatureCols() - { - Hashtable fcols = new Hashtable(); - if (ap.av.featuresDisplayed == null) - { - return fcols; - } - Enumeration en = ap.av.featuresDisplayed.keys(); - FeatureRenderer fr = ap.getSeqPanel().seqCanvas.getFeatureRenderer(); // consider - // higher - // level - // method ? - while (en.hasMoreElements()) - { - Object col = en.nextElement(); - fcols.put(col, fr.featureColours.get(col)); - } - return fcols; - } - public void close_actionPerformed(ActionEvent e) { try diff --git a/src/jalview/gui/AppJmol.java b/src/jalview/gui/AppJmol.java index 4dfd18a..09b0fdd 100644 --- a/src/jalview/gui/AppJmol.java +++ b/src/jalview/gui/AppJmol.java @@ -1074,7 +1074,7 @@ public class AppJmol extends GStructureViewer implements Runnable, // Set the colour using the current view for the associated alignframe for (AlignmentPanel ap : _colourwith) { - jmb.colourBySequence(ap.av.showSequenceFeatures, ap); + jmb.colourBySequence(ap.av.isShowSequenceFeatures(), ap); } } } diff --git a/src/jalview/gui/AppJmolBinding.java b/src/jalview/gui/AppJmolBinding.java index 7fa300e..42a2f74 100644 --- a/src/jalview/gui/AppJmolBinding.java +++ b/src/jalview/gui/AppJmolBinding.java @@ -58,11 +58,11 @@ public class AppJmolBinding extends jalview.ext.jmol.JalviewJmolBinding { AlignmentPanel ap = (alignment == null) ? appJmolWindow.ap : (AlignmentPanel) alignment; - if (ap.av.showSequenceFeatures) + if (ap.av.isShowSequenceFeatures()) { if (fr == null) { - fr = ap.cloneFeatureRenderer(); + fr = (jalview.gui.FeatureRenderer) ap.cloneFeatureRenderer(); } else { @@ -133,7 +133,7 @@ public class AppJmolBinding extends jalview.ext.jmol.JalviewJmolBinding return; if (!isLoadingFromArchive()) { - colourBySequence(ap.av.getShowSequenceFeatures(), ap); + colourBySequence(ap.av.isShowSequenceFeatures(), ap); } } diff --git a/src/jalview/gui/BlogReader.java b/src/jalview/gui/BlogReader.java index 7a1065d..7d4399d 100644 --- a/src/jalview/gui/BlogReader.java +++ b/src/jalview/gui/BlogReader.java @@ -25,10 +25,10 @@ import jalview.util.MessageManager; import java.awt.BorderLayout; import java.awt.Component; +import java.awt.Dialog.ModalExclusionType; import java.awt.Dimension; import java.awt.Font; import java.awt.Rectangle; -import java.awt.Dialog.ModalExclusionType; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; @@ -198,7 +198,7 @@ public class BlogReader extends JPanel { if (parent != null) { - Cache.log.info("News window closed."); + Cache.log.debug("News window closed."); jd = null; parent.showNews(false); } @@ -246,7 +246,7 @@ public class BlogReader extends JPanel public BlogReader(Desktop desktop) { - Cache.log.info("Constructing news reader."); + Cache.log.debug("Constructing news reader."); parent = desktop; _channelModel = new ChannelListModel(); @@ -275,10 +275,10 @@ public class BlogReader extends JPanel if (setvisible) { - Cache.log.info("Will show jalview news automatically"); + Cache.log.debug("Will show jalview news automatically"); showNews(); } - Cache.log.info("Completed construction of reader."); + Cache.log.debug("Completed construction of reader."); } @@ -334,7 +334,7 @@ public class BlogReader extends JPanel jd.initDialogFrame(me, false, false, MessageManager.getString("label.news_from_jalview"), bounds.width, bounds.height); jd.frame.setModalExclusionType(ModalExclusionType.NO_EXCLUDE); - Cache.log.info("Displaying news."); + Cache.log.debug("Displaying news."); jd.waitForInput(); } } @@ -421,7 +421,7 @@ public class BlogReader extends JPanel { jalview.bin.Cache.setDateProperty("JALVIEW_NEWS_RSS_LASTMODIFIED", lastDate); - jalview.bin.Cache.log.info("Saved last read date as " + jalview.bin.Cache.log.debug("Saved last read date as " + jalview.bin.Cache.date_format.format(lastDate)); } @@ -758,16 +758,16 @@ public class BlogReader extends JPanel + jalview.bin.Cache.date_format.format(lastread.getTime())); if (me.isNewsNew()) { - Cache.log.info("There is news to read."); + Cache.log.debug("There is news to read."); } else { - Cache.log.info("There is no new news."); + Cache.log.debug("There is no new news."); me.xf.setTitle("Testing : Last read is " + me.lastDate); me.showNews(); me.xf.toFront(); } - Cache.log.info("Waiting for closure."); + Cache.log.debug("Waiting for closure."); do { try @@ -781,11 +781,11 @@ public class BlogReader extends JPanel if (me.isNewsNew()) { - Cache.log.info("Still new news after reader displayed."); + Cache.log.debug("Still new news after reader displayed."); } if (lastread.getTime().before(me.lastDate)) { - Cache.log.info("The news was read."); + Cache.log.debug("The news was read."); lastread.setTime(me.lastDate); } else diff --git a/src/jalview/gui/ChimeraViewFrame.java b/src/jalview/gui/ChimeraViewFrame.java index 2f84d28..48123fa 100644 --- a/src/jalview/gui/ChimeraViewFrame.java +++ b/src/jalview/gui/ChimeraViewFrame.java @@ -840,8 +840,13 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, { if (progressBar != null) { - progressBar.setProgressBar( - MessageManager.getString("label.state_completed"), hdl); + progressBar + .setProgressBar( + pdbid + + " " + + MessageManager + .getString("label.state_completed"), + hdl); } } /* @@ -979,7 +984,7 @@ public class ChimeraViewFrame extends GStructureViewer implements Runnable, // Set the colour using the current view for the associated alignframe for (AlignmentPanel ap : _colourwith) { - jmb.colourBySequence(ap.av.showSequenceFeatures, ap); + jmb.colourBySequence(ap.av.isShowSequenceFeatures(), ap); } } } diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java index 007fefd..b8f629a 100644 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@ -631,38 +631,85 @@ public class Desktop extends jalview.jbgui.GDesktop implements * Adds and opens the given frame to the desktop * * @param frame - * DOCUMENT ME! + * Frame to show * @param title - * DOCUMENT ME! + * Visible Title * @param w - * DOCUMENT ME! + * width * @param h - * DOCUMENT ME! + * height */ public static synchronized void addInternalFrame( final JInternalFrame frame, String title, int w, int h) { - addInternalFrame(frame, title, w, h, true); + addInternalFrame(frame, title, true, w, h, true); } + /** - * DOCUMENT ME! + * Add an internal frame to the Jalview desktop * * @param frame - * DOCUMENT ME! + * Frame to show * @param title - * DOCUMENT ME! + * Visible Title + * @param makeVisible + * When true, display frame immediately, otherwise, caller must call + * setVisible themselves. * @param w - * DOCUMENT ME! + * width * @param h - * DOCUMENT ME! + * height + */ + public static synchronized void addInternalFrame( + final JInternalFrame frame, String title, boolean makeVisible, + int w, int h) + { + addInternalFrame(frame, title, makeVisible, w, h, true); + } + + /** + * Add an internal frame to the Jalview desktop and make it visible + * + * @param frame + * Frame to show + * @param title + * Visible Title + * @param w + * width + * @param h + * height * @param resizable - * DOCUMENT ME! + * Allow resize */ public static synchronized void addInternalFrame( final JInternalFrame frame, String title, int w, int h, boolean resizable) { + addInternalFrame(frame, title, true, w, h, resizable); + } + + /** + * Add an internal frame to the Jalview desktop + * + * @param frame + * Frame to show + * @param title + * Visible Title + * @param makeVisible + * When true, display frame immediately, otherwise, caller must call + * setVisible themselves. + * @param w + * width + * @param h + * height + * @param resizable + * Allow resize + */ + public static synchronized void addInternalFrame( + final JInternalFrame frame, String title, boolean makeVisible, + int w, int h, boolean resizable) + { // TODO: allow callers to determine X and Y position of frame (eg. via // bounds object). @@ -687,7 +734,7 @@ public class Desktop extends jalview.jbgui.GDesktop implements openFrameCount++; - frame.setVisible(true); + frame.setVisible(makeVisible); frame.setClosable(true); frame.setResizable(resizable); frame.setMaximizable(resizable); @@ -1064,7 +1111,9 @@ public class Desktop extends jalview.jbgui.GDesktop implements { CutAndPasteTransfer cap = new CutAndPasteTransfer(); cap.setForInput(viewport); - Desktop.addInternalFrame(cap, MessageManager.getString("label.cut_paste_alignmen_file"), 600, 500); + Desktop.addInternalFrame(cap, + MessageManager.getString("label.cut_paste_alignmen_file"), + true, 600, 500); } /* diff --git a/src/jalview/gui/FeatureColourChooser.java b/src/jalview/gui/FeatureColourChooser.java index 8ab7c85..d1d1b6d 100644 --- a/src/jalview/gui/FeatureColourChooser.java +++ b/src/jalview/gui/FeatureColourChooser.java @@ -109,10 +109,10 @@ public class FeatureColourChooser extends JalviewDialog } }); - float mm[] = ((float[][]) fr.minmax.get(type))[0]; + float mm[] = ((float[][]) fr.getMinMax().get(type))[0]; min = mm[0]; max = mm[1]; - oldcs = fr.featureColours.get(type); + oldcs = fr.getFeatureColours().get(type); if (oldcs instanceof GraduatedColor) { if (((GraduatedColor) oldcs).isAutoScale()) @@ -470,7 +470,7 @@ public class FeatureColourChooser extends JalviewDialog maxColour.setForeground(oldmaxColour); minColour.setForeground(oldminColour); } - fr.featureColours.put(type, acg); + fr.setColour(type, acg); cs = acg; ap.paintAlignment(false); } @@ -495,7 +495,7 @@ public class FeatureColourChooser extends JalviewDialog void reset() { - fr.featureColours.put(type, oldcs); + fr.setColour(type, oldcs); ap.paintAlignment(false); cs = null; } diff --git a/src/jalview/gui/FeatureRenderer.java b/src/jalview/gui/FeatureRenderer.java index cbdf2ef..3ce831e 100644 --- a/src/jalview/gui/FeatureRenderer.java +++ b/src/jalview/gui/FeatureRenderer.java @@ -20,59 +20,46 @@ */ package jalview.gui; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -import java.awt.*; -import java.awt.event.*; -import java.awt.image.*; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; - -import javax.swing.*; - -import jalview.datamodel.*; +import jalview.datamodel.SearchResults; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; import jalview.schemes.GraduatedColor; import jalview.util.MessageManager; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.JColorChooser; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSpinner; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingConstants; + /** * DOCUMENT ME! * * @author $author$ * @version $Revision$ */ -public class FeatureRenderer implements jalview.api.FeatureRenderer +public class FeatureRenderer extends jalview.renderer.seqfeatures.FeatureRenderer implements jalview.api.FeatureRenderer { - AlignmentPanel ap; - - AlignViewport av; - Color resBoxColour; - /** - * global transparency for feature - */ - float transparency = 1.0f; - - FontMetrics fm; - - int charOffset; - - Map featureColours = new ConcurrentHashMap(); - - // A higher level for grouping features of a - // particular type - Map featureGroups = new ConcurrentHashMap(); - - // This is actually an Integer held in the hashtable, - // Retrieved using the key feature type - Object currentColour; - - String[] renderOrder; - - PropertyChangeSupport changeSupport = new PropertyChangeSupport(this); - - Vector allfeatures; + AlignmentPanel ap; /** * Creates a new FeatureRenderer object. @@ -82,6 +69,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer */ public FeatureRenderer(AlignmentPanel ap) { + super(); this.ap = ap; this.av = ap.av; if (ap != null && ap.getSeqPanel() != null && ap.getSeqPanel().seqCanvas != null @@ -91,895 +79,6 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer } } - public class FeatureRendererSettings implements Cloneable - { - String[] renderOrder; - - Map featureGroups; - - Map featureColours; - - float transparency; - - Map featureOrder; - - public FeatureRendererSettings(String[] renderOrder, - Hashtable featureGroups, Hashtable featureColours, - float transparency, Hashtable featureOrder) - { - super(); - this.renderOrder = renderOrder; - this.featureGroups = featureGroups; - this.featureColours = featureColours; - this.transparency = transparency; - this.featureOrder = featureOrder; - } - - /** - * create an independent instance of the feature renderer settings - * - * @param fr - */ - public FeatureRendererSettings(FeatureRenderer fr) - { - renderOrder = null; - featureGroups = new ConcurrentHashMap(); - featureColours = new ConcurrentHashMap(); - featureOrder = new ConcurrentHashMap(); - if (fr.renderOrder != null) - { - this.renderOrder = new String[fr.renderOrder.length]; - System.arraycopy(fr.renderOrder, 0, renderOrder, 0, - fr.renderOrder.length); - } - if (fr.featureGroups != null) - { - this.featureGroups = new ConcurrentHashMap(fr.featureGroups); - } - if (fr.featureColours != null) - { - this.featureColours = new ConcurrentHashMap(fr.featureColours); - } - Iterator en = fr.featureColours.keySet().iterator(); - while (en.hasNext()) - { - Object next = en.next(); - Object val = featureColours.get(next); - if (val instanceof GraduatedColor) - { - featureColours - .put(next, new GraduatedColor((GraduatedColor) val)); - } - } - this.transparency = fr.transparency; - if (fr.featureOrder != null) - { - this.featureOrder = new ConcurrentHashMap(fr.featureOrder); - } - } - } - - public FeatureRendererSettings getSettings() - { - return new FeatureRendererSettings(this); - } - - public void transferSettings(FeatureRendererSettings fr) - { - this.renderOrder = fr.renderOrder; - this.featureGroups = fr.featureGroups; - this.featureColours = fr.featureColours; - this.transparency = fr.transparency; - this.featureOrder = fr.featureOrder; - } - - /** - * update from another feature renderer - * - * @param fr - * settings to copy - */ - public void transferSettings(FeatureRenderer fr) - { - FeatureRendererSettings frs = new FeatureRendererSettings(fr); - this.renderOrder = frs.renderOrder; - this.featureGroups = frs.featureGroups; - this.featureColours = frs.featureColours; - this.transparency = frs.transparency; - this.featureOrder = frs.featureOrder; - if (av != null && av != fr.av) - { - // copy over the displayed feature settings - if (fr.av != null) - { - if (fr.av.featuresDisplayed != null) - { - // update display settings - if (av.featuresDisplayed == null) - { - av.featuresDisplayed = new Hashtable(fr.av.featuresDisplayed); - } - else - { - av.featuresDisplayed.clear(); - Enumeration en = fr.av.featuresDisplayed.keys(); - while (en.hasMoreElements()) - { - av.featuresDisplayed.put(en.nextElement(), Boolean.TRUE); - } - - } - } - } - } - } - - BufferedImage offscreenImage; - - boolean offscreenRender = false; - - public Color findFeatureColour(Color initialCol, SequenceI seq, int res) - { - return new Color(findFeatureColour(initialCol.getRGB(), seq, res)); - } - - /** - * This is used by the Molecule Viewer and Overview to get the accurate - * colourof the rendered sequence - */ - public synchronized int findFeatureColour(int initialCol, SequenceI seq, - int column) - { - if (!av.showSequenceFeatures) - { - return initialCol; - } - - if (seq != lastSeq) - { - lastSeq = seq; - sequenceFeatures = lastSeq.getDatasetSequence().getSequenceFeatures(); - if (sequenceFeatures != null) - { - sfSize = sequenceFeatures.length; - } - } - - if (sequenceFeatures != lastSeq.getDatasetSequence() - .getSequenceFeatures()) - { - sequenceFeatures = lastSeq.getDatasetSequence().getSequenceFeatures(); - if (sequenceFeatures != null) - { - sfSize = sequenceFeatures.length; - } - } - - if (sequenceFeatures == null || sfSize == 0) - { - return initialCol; - } - - if (jalview.util.Comparison.isGap(lastSeq.getCharAt(column))) - { - return Color.white.getRGB(); - } - - // Only bother making an offscreen image if transparency is applied - if (transparency != 1.0f && offscreenImage == null) - { - offscreenImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); - } - - currentColour = null; - // TODO: non-threadsafe - each rendering thread needs its own instance of - // the feature renderer - or this should be synchronized. - offscreenRender = true; - - if (offscreenImage != null) - { - offscreenImage.setRGB(0, 0, initialCol); - drawSequence(offscreenImage.getGraphics(), lastSeq, column, column, 0); - - return offscreenImage.getRGB(0, 0); - } - else - { - drawSequence(null, lastSeq, lastSeq.findPosition(column), -1, -1); - - if (currentColour == null) - { - return initialCol; - } - else - { - return ((Integer) currentColour).intValue(); - } - } - - } - - /** - * DOCUMENT ME! - * - * @param g - * DOCUMENT ME! - * @param seq - * DOCUMENT ME! - * @param sg - * DOCUMENT ME! - * @param start - * DOCUMENT ME! - * @param end - * DOCUMENT ME! - * @param x1 - * DOCUMENT ME! - * @param y1 - * DOCUMENT ME! - * @param width - * DOCUMENT ME! - * @param height - * DOCUMENT ME! - */ - // String type; - // SequenceFeature sf; - SequenceI lastSeq; - - SequenceFeature[] sequenceFeatures; - - int sfSize, sfindex, spos, epos; - - /** - * show scores as heights - */ - protected boolean varyHeight = false; - - synchronized public void drawSequence(Graphics g, SequenceI seq, - int start, int end, int y1) - { - - if (seq.getDatasetSequence().getSequenceFeatures() == null - || seq.getDatasetSequence().getSequenceFeatures().length == 0) - { - return; - } - - if (g != null) - { - fm = g.getFontMetrics(); - } - - if (av.featuresDisplayed == null || renderOrder == null - || newFeatureAdded) - { - findAllFeatures(); - if (av.featuresDisplayed.size() < 1) - { - return; - } - - sequenceFeatures = seq.getDatasetSequence().getSequenceFeatures(); - } - - if (lastSeq == null - || seq != lastSeq - || seq.getDatasetSequence().getSequenceFeatures() != sequenceFeatures) - { - lastSeq = seq; - sequenceFeatures = seq.getDatasetSequence().getSequenceFeatures(); - } - - if (transparency != 1 && g != null) - { - Graphics2D g2 = (Graphics2D) g; - g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, - transparency)); - } - - if (!offscreenRender) - { - spos = lastSeq.findPosition(start); - epos = lastSeq.findPosition(end); - } - - sfSize = sequenceFeatures.length; - String type; - for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++) - { - type = renderOrder[renderIndex]; - - if (type == null || !av.featuresDisplayed.containsKey(type)) - { - continue; - } - - // loop through all features in sequence to find - // current feature to render - for (sfindex = 0; sfindex < sfSize; sfindex++) - { - if (!sequenceFeatures[sfindex].type.equals(type)) - { - continue; - } - - if (featureGroups != null - && sequenceFeatures[sfindex].featureGroup != null - && sequenceFeatures[sfindex].featureGroup.length() != 0 - && featureGroups - .containsKey(sequenceFeatures[sfindex].featureGroup) - && !((Boolean) featureGroups - .get(sequenceFeatures[sfindex].featureGroup)) - .booleanValue()) - { - continue; - } - - if (!offscreenRender - && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex] - .getEnd() < spos)) - { - continue; - } - - if (offscreenRender && offscreenImage == null) - { - if (sequenceFeatures[sfindex].begin <= start - && sequenceFeatures[sfindex].end >= start) - { - // this is passed out to the overview and other sequence renderers - // (e.g. molecule viewer) to get displayed colour for rendered - // sequence - currentColour = new Integer( - getColour(sequenceFeatures[sfindex]).getRGB()); - // used to be retreived from av.featuresDisplayed - // currentColour = av.featuresDisplayed - // .get(sequenceFeatures[sfindex].type); - - } - } - else if (sequenceFeatures[sfindex].type.equals("disulfide bond")) - { - - renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - getColour(sequenceFeatures[sfindex]) - // new Color(((Integer) av.featuresDisplayed - // .get(sequenceFeatures[sfindex].type)).intValue()) - , start, end, y1); - renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]) - // new Color(((Integer) av.featuresDisplayed - // .get(sequenceFeatures[sfindex].type)).intValue()) - , start, end, y1); - - } - else if (showFeature(sequenceFeatures[sfindex])) - { - if (av.showSeqFeaturesHeight - && sequenceFeatures[sfindex].score != Float.NaN) - { - renderScoreFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]), start, end, y1, - normaliseScore(sequenceFeatures[sfindex])); - } - else - { - renderFeature(g, seq, - seq.findIndex(sequenceFeatures[sfindex].begin) - 1, - seq.findIndex(sequenceFeatures[sfindex].end) - 1, - getColour(sequenceFeatures[sfindex]), start, end, y1); - } - } - - } - - } - - if (transparency != 1.0f && g != null) - { - Graphics2D g2 = (Graphics2D) g; - g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, - 1.0f)); - } - } - - Hashtable minmax = new Hashtable(); - - /** - * normalise a score against the max/min bounds for the feature type. - * - * @param sequenceFeature - * @return byte[] { signed, normalised signed (-127 to 127) or unsigned - * (0-255) value. - */ - private final byte[] normaliseScore(SequenceFeature sequenceFeature) - { - float[] mm = ((float[][]) minmax.get(sequenceFeature.type))[0]; - final byte[] r = new byte[] - { 0, (byte) 255 }; - if (mm != null) - { - if (r[0] != 0 || mm[0] < 0.0) - { - r[0] = 1; - r[1] = (byte) ((int) 128.0 + 127.0 * (sequenceFeature.score / mm[1])); - } - else - { - r[1] = (byte) ((int) 255.0 * (sequenceFeature.score / mm[1])); - } - } - return r; - } - - char s; - - int i; - - void renderFeature(Graphics g, SequenceI seq, int fstart, int fend, - Color featureColour, int start, int end, int y1) - { - - if (((fstart <= end) && (fend >= start))) - { - if (fstart < start) - { // fix for if the feature we have starts before the sequence start, - fstart = start; // but the feature end is still valid!! - } - - if (fend >= end) - { - fend = end; - } - int pady = (y1 + av.charHeight) - av.charHeight / 5; - for (i = fstart; i <= fend; i++) - { - s = seq.getCharAt(i); - - if (jalview.util.Comparison.isGap(s)) - { - continue; - } - - g.setColor(featureColour); - - g.fillRect((i - start) * av.charWidth, y1, av.charWidth, - av.charHeight); - - if (offscreenRender || !av.validCharWidth) - { - continue; - } - - g.setColor(Color.white); - charOffset = (av.charWidth - fm.charWidth(s)) / 2; - g.drawString(String.valueOf(s), charOffset - + (av.charWidth * (i - start)), pady); - - } - } - } - - void renderScoreFeature(Graphics g, SequenceI seq, int fstart, int fend, - Color featureColour, int start, int end, int y1, byte[] bs) - { - - if (((fstart <= end) && (fend >= start))) - { - if (fstart < start) - { // fix for if the feature we have starts before the sequence start, - fstart = start; // but the feature end is still valid!! - } - - if (fend >= end) - { - fend = end; - } - int pady = (y1 + av.charHeight) - av.charHeight / 5; - int ystrt = 0, yend = av.charHeight; - if (bs[0] != 0) - { - // signed - zero is always middle of residue line. - if (bs[1] < 128) - { - yend = av.charHeight * (128 - bs[1]) / 512; - ystrt = av.charHeight - yend / 2; - } - else - { - ystrt = av.charHeight / 2; - yend = av.charHeight * (bs[1] - 128) / 512; - } - } - else - { - yend = av.charHeight * bs[1] / 255; - ystrt = av.charHeight - yend; - - } - for (i = fstart; i <= fend; i++) - { - s = seq.getCharAt(i); - - if (jalview.util.Comparison.isGap(s)) - { - continue; - } - - g.setColor(featureColour); - int x = (i - start) * av.charWidth; - g.drawRect(x, y1, av.charWidth, av.charHeight); - g.fillRect(x, y1 + ystrt, av.charWidth, yend); - - if (offscreenRender || !av.validCharWidth) - { - continue; - } - - g.setColor(Color.black); - charOffset = (av.charWidth - fm.charWidth(s)) / 2; - g.drawString(String.valueOf(s), charOffset - + (av.charWidth * (i - start)), pady); - - } - } - } - - boolean newFeatureAdded = false; - - /** - * Called when alignment in associated view has new/modified features to - * discover and display. - * - */ - public void featuresAdded() - { - lastSeq = null; - findAllFeatures(); - } - - boolean findingFeatures = false; - - /** - * search the alignment for all new features, give them a colour and display - * them. Then fires a PropertyChangeEvent on the changeSupport object. - * - */ - void findAllFeatures() - { - synchronized (firing) - { - if (firing.equals(Boolean.FALSE)) - { - firing = Boolean.TRUE; - findAllFeatures(true); // add all new features as visible - changeSupport.firePropertyChange("changeSupport", null, null); - firing = Boolean.FALSE; - } - } - } - - /** - * Searches alignment for all features and updates colours - * - * @param newMadeVisible - * if true newly added feature types will be rendered immediatly - */ - synchronized void findAllFeatures(boolean newMadeVisible) - { - newFeatureAdded = false; - - if (findingFeatures) - { - newFeatureAdded = true; - return; - } - - findingFeatures = true; - - if (av.featuresDisplayed == null) - { - av.featuresDisplayed = new Hashtable(); - } - - allfeatures = new Vector(); - Vector oldfeatures = new Vector(); - if (renderOrder != null) - { - for (int i = 0; i < renderOrder.length; i++) - { - if (renderOrder[i] != null) - { - oldfeatures.addElement(renderOrder[i]); - } - } - } - if (minmax == null) - { - minmax = new Hashtable(); - } - AlignmentI alignment = av.getAlignment(); - for (int i = 0; i < alignment.getHeight(); i++) - { - SequenceFeature[] features = alignment.getSequenceAt(i) - .getDatasetSequence().getSequenceFeatures(); - - if (features == null) - { - continue; - } - - int index = 0; - while (index < features.length) - { - if (!av.featuresDisplayed.containsKey(features[index].getType())) - { - - if (featureGroups.containsKey(features[index].getType())) - { - boolean visible = ((Boolean) featureGroups - .get(features[index].featureGroup)).booleanValue(); - - if (!visible) - { - index++; - continue; - } - } - - if (!(features[index].begin == 0 && features[index].end == 0)) - { - // If beginning and end are 0, the feature is for the whole sequence - // and we don't want to render the feature in the normal way - - if (newMadeVisible - && !oldfeatures.contains(features[index].getType())) - { - // this is a new feature type on the alignment. Mark it for - // display. - av.featuresDisplayed.put(features[index].getType(), - new Integer(getColour(features[index].getType()) - .getRGB())); - setOrder(features[index].getType(), 0); - } - } - } - if (!allfeatures.contains(features[index].getType())) - { - allfeatures.addElement(features[index].getType()); - } - if (features[index].score != Float.NaN) - { - int nonpos = features[index].getBegin() >= 1 ? 0 : 1; - float[][] mm = (float[][]) minmax.get(features[index].getType()); - if (mm == null) - { - mm = new float[][] - { null, null }; - minmax.put(features[index].getType(), mm); - } - if (mm[nonpos] == null) - { - mm[nonpos] = new float[] - { features[index].score, features[index].score }; - - } - else - { - if (mm[nonpos][0] > features[index].score) - { - mm[nonpos][0] = features[index].score; - } - if (mm[nonpos][1] < features[index].score) - { - mm[nonpos][1] = features[index].score; - } - } - } - index++; - } - } - updateRenderOrder(allfeatures); - findingFeatures = false; - } - - protected Boolean firing = Boolean.FALSE; - - /** - * replaces the current renderOrder with the unordered features in - * allfeatures. The ordering of any types in both renderOrder and allfeatures - * is preserved, and all new feature types are rendered on top of the existing - * types, in the order given by getOrder or the order given in allFeatures. - * Note. this operates directly on the featureOrder hash for efficiency. TODO: - * eliminate the float storage for computing/recalling the persistent ordering - * New Cability: updates min/max for colourscheme range if its dynamic - * - * @param allFeatures - */ - private void updateRenderOrder(Vector allFeatures) - { - Vector allfeatures = new Vector(allFeatures); - String[] oldRender = renderOrder; - renderOrder = new String[allfeatures.size()]; - Object mmrange, fc = null; - boolean initOrders = (featureOrder == null); - int opos = 0; - if (oldRender != null && oldRender.length > 0) - { - for (int j = 0; j < oldRender.length; j++) - { - if (oldRender[j] != null) - { - if (initOrders) - { - setOrder(oldRender[j], (1 - (1 + (float) j) - / (float) oldRender.length)); - } - if (allfeatures.contains(oldRender[j])) - { - renderOrder[opos++] = oldRender[j]; // existing features always - // appear below new features - allfeatures.removeElement(oldRender[j]); - if (minmax != null) - { - mmrange = minmax.get(oldRender[j]); - if (mmrange != null) - { - fc = featureColours.get(oldRender[j]); - if (fc != null && fc instanceof GraduatedColor - && ((GraduatedColor) fc).isAutoScale()) - { - ((GraduatedColor) fc).updateBounds( - ((float[][]) mmrange)[0][0], - ((float[][]) mmrange)[0][1]); - } - } - } - } - } - } - } - if (allfeatures.size() == 0) - { - // no new features - leave order unchanged. - return; - } - int i = allfeatures.size() - 1; - int iSize = i; - boolean sort = false; - String[] newf = new String[allfeatures.size()]; - float[] sortOrder = new float[allfeatures.size()]; - Enumeration en = allfeatures.elements(); - // sort remaining elements - while (en.hasMoreElements()) - { - newf[i] = en.nextElement().toString(); - if (minmax != null) - { - // update from new features minmax if necessary - mmrange = minmax.get(newf[i]); - if (mmrange != null) - { - fc = featureColours.get(newf[i]); - if (fc != null && fc instanceof GraduatedColor - && ((GraduatedColor) fc).isAutoScale()) - { - ((GraduatedColor) fc).updateBounds(((float[][]) mmrange)[0][0], - ((float[][]) mmrange)[0][1]); - } - } - } - if (initOrders || !featureOrder.containsKey(newf[i])) - { - int denom = initOrders ? allfeatures.size() : featureOrder.size(); - // new unordered feature - compute persistent ordering at head of - // existing features. - setOrder(newf[i], i / (float) denom); - } - // set order from newly found feature from persisted ordering. - sortOrder[i] = 2 - ((Float) featureOrder.get(newf[i])).floatValue(); - if (i < iSize) - { - // only sort if we need to - sort = sort || sortOrder[i] > sortOrder[i + 1]; - } - i--; - } - if (iSize > 1 && sort) - { - jalview.util.QuickSort.sort(sortOrder, newf); - } - sortOrder = null; - System.arraycopy(newf, 0, renderOrder, opos, newf.length); - } - - /** - * get a feature style object for the given type string. Creates a - * java.awt.Color for a featureType with no existing colourscheme. TODO: - * replace return type with object implementing standard abstract colour/style - * interface - * - * @param featureType - * @return java.awt.Color or GraduatedColor - */ - public Object getFeatureStyle(String featureType) - { - Object fc = featureColours.get(featureType); - if (fc == null) - { - jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(); - Color col = ucs.createColourFromName(featureType); - featureColours.put(featureType, fc = col); - } - return fc; - } - - /** - * return a nominal colour for this feature - * - * @param featureType - * @return standard color, or maximum colour for graduated colourscheme - */ - public Color getColour(String featureType) - { - Object fc = getFeatureStyle(featureType); - - if (fc instanceof Color) - { - return (Color) fc; - } - else - { - if (fc instanceof GraduatedColor) - { - return ((GraduatedColor) fc).getMaxColor(); - } - } - throw new Error(MessageManager.formatMessage("error.implementation_error_unrecognised_render_object_for_features_type", new String[]{fc.getClass().toString(),featureType})); - } - - /** - * calculate the render colour for a specific feature using current feature - * settings. - * - * @param feature - * @return render colour for the given feature - */ - public Color getColour(SequenceFeature feature) - { - Object fc = getFeatureStyle(feature.getType()); - if (fc instanceof Color) - { - return (Color) fc; - } - else - { - if (fc instanceof GraduatedColor) - { - return ((GraduatedColor) fc).findColor(feature); - } - } - throw new Error(MessageManager.formatMessage("error.implementation_error_unrecognised_render_object_for_features_type", new String[]{fc.getClass().toString(),feature.getType()})); - } - - private boolean showFeature(SequenceFeature sequenceFeature) - { - Object fc = getFeatureStyle(sequenceFeature.type); - if (fc instanceof GraduatedColor) - { - return ((GraduatedColor) fc).isColored(sequenceFeature); - } - else - { - return true; - } - } - // // ///////////// // // Feature Editing Dialog // // Will be refactored in next release. @@ -1235,7 +334,9 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer lastDescriptionAdded = description.getText().replaceAll("\n", " "); // TODO: determine if the null feature group is valid if (lastFeatureGroupAdded.length() < 1) + { lastFeatureGroupAdded = null; + } } if (!newFeatures) @@ -1253,7 +354,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer sf.description = lastDescriptionAdded; setColour(sf.type, fcol); - av.featuresDisplayed.put(sf.type, getColour(sf.type)); + getFeaturesDisplayed().setVisible(sf.type); try { @@ -1274,27 +375,19 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer for (int i = 0; i < sequences.length; i++) { features[i].type = lastFeatureAdded; - if (lastFeatureGroupAdded != null) - features[i].featureGroup = lastFeatureGroupAdded; + // fix for JAL-1538 - always set feature group here + features[i].featureGroup = lastFeatureGroupAdded; features[i].description = lastDescriptionAdded; sequences[i].addSequenceFeature(features[i]); ffile.parseDescriptionHTML(features[i], false); } - if (av.featuresDisplayed == null) - { - av.featuresDisplayed = new Hashtable(); - } - if (lastFeatureGroupAdded != null) { - if (featureGroups == null) - featureGroups = new Hashtable(); - featureGroups.put(lastFeatureGroupAdded, new Boolean(true)); + setGroupVisibility(lastFeatureGroupAdded, true); } setColour(lastFeatureAdded, fcol); - av.featuresDisplayed.put(lastFeatureAdded, - getColour(lastFeatureAdded)); + setVisible(lastFeatureAdded); findAllFeatures(false); @@ -1313,6 +406,7 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer return true; } + /** * update the amend feature button dependent on the given style * @@ -1340,145 +434,4 @@ public class FeatureRenderer implements jalview.api.FeatureRenderer // colour.setForeground(colour.getBackground()); } } - - public void setColour(String featureType, Object col) - { - // overwrite - // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof - // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null; - // Object c = featureColours.get(featureType); - // if (c == null || c instanceof Color || (c instanceof GraduatedColor && - // !((GraduatedColor)c).getMaxColor().equals(_col))) - { - featureColours.put(featureType, col); - } - } - - public void setTransparency(float value) - { - transparency = value; - } - - public float getTransparency() - { - return transparency; - } - - /** - * Replace current ordering with new ordering - * - * @param data - * { String(Type), Colour(Type), Boolean(Displayed) } - */ - public void setFeaturePriority(Object[][] data) - { - setFeaturePriority(data, true); - } - - /** - * - * @param data - * { String(Type), Colour(Type), Boolean(Displayed) } - * @param visibleNew - * when true current featureDisplay list will be cleared - */ - public void setFeaturePriority(Object[][] data, boolean visibleNew) - { - if (visibleNew) - { - if (av.featuresDisplayed != null) - { - av.featuresDisplayed.clear(); - } - else - { - av.featuresDisplayed = new Hashtable(); - } - } - if (data == null) - { - return; - } - - // The feature table will display high priority - // features at the top, but theses are the ones - // we need to render last, so invert the data - renderOrder = new String[data.length]; - - if (data.length > 0) - { - for (int i = 0; i < data.length; i++) - { - String type = data[i][0].toString(); - setColour(type, data[i][1]); // todo : typesafety - feature color - // interface object - if (((Boolean) data[i][2]).booleanValue()) - { - av.featuresDisplayed.put(type, new Integer(getColour(type) - .getRGB())); - } - - renderOrder[data.length - i - 1] = type; - } - } - - } - - Map featureOrder = null; - - /** - * analogous to colour - store a normalized ordering for all feature types in - * this rendering context. - * - * @param type - * Feature type string - * @param position - * normalized priority - 0 means always appears on top, 1 means - * always last. - */ - public float setOrder(String type, float position) - { - if (featureOrder == null) - { - featureOrder = new Hashtable(); - } - featureOrder.put(type, new Float(position)); - return position; - } - - /** - * get the global priority (0 (top) to 1 (bottom)) - * - * @param type - * @return [0,1] or -1 for a type without a priority - */ - public float getOrder(String type) - { - if (featureOrder != null) - { - if (featureOrder.containsKey(type)) - { - return ((Float) featureOrder.get(type)).floatValue(); - } - } - return -1; - } - - /** - * @param listener - * @see java.beans.PropertyChangeSupport#addPropertyChangeListener(java.beans.PropertyChangeListener) - */ - public void addPropertyChangeListener(PropertyChangeListener listener) - { - changeSupport.addPropertyChangeListener(listener); - } - - /** - * @param listener - * @see java.beans.PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener) - */ - public void removePropertyChangeListener(PropertyChangeListener listener) - { - changeSupport.removePropertyChangeListener(listener); - } } diff --git a/src/jalview/gui/FeatureSettings.java b/src/jalview/gui/FeatureSettings.java index 9748f42..3475fe3 100644 --- a/src/jalview/gui/FeatureSettings.java +++ b/src/jalview/gui/FeatureSettings.java @@ -20,12 +20,8 @@ */ package jalview.gui; -import jalview.analysis.AlignmentSorter; import jalview.bin.Cache; -import jalview.commands.OrderCommand; -import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceFeature; -import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.gui.Help.HelpId; import jalview.io.JalviewFileChooser; @@ -56,10 +52,10 @@ import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; -import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.List; +import java.util.Set; import java.util.Vector; import javax.help.HelpSetException; @@ -107,6 +103,8 @@ public class FeatureSettings extends JPanel Object[][] originalData; + private float originalTransparency; + final JInternalFrame frame; JScrollPane scrollPane = new JScrollPane(); @@ -123,8 +121,8 @@ public class FeatureSettings extends JPanel { this.af = af; fr = af.getFeatureRenderer(); - - transparency.setMaximum(100 - (int) (fr.transparency * 100)); + // allow transparency to be recovered + transparency.setMaximum(100 - (int) ((originalTransparency=fr.getTransparency()) * 100)); try { @@ -165,8 +163,8 @@ public class FeatureSettings extends JPanel if (SwingUtilities.isRightMouseButton(evt)) { popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0), - table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(), - evt.getY()); + table.getValueAt(selectedRow, 1), fr.getMinMax(), + evt.getX(), evt.getY()); } else if (evt.getClickCount() == 2) { @@ -185,7 +183,8 @@ public class FeatureSettings extends JPanel if (evt.isPopupTrigger()) { popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0), - table.getValueAt(selectedRow, 1), fr.minmax, evt.getX(), + table.getValueAt(selectedRow, 1), fr.getMinMax(), + evt.getX(), evt.getY()); } } @@ -222,8 +221,7 @@ public class FeatureSettings extends JPanel dassourceBrowser = new DasSourceBrowser(this); dasSettingsPane.add(dassourceBrowser, BorderLayout.CENTER); - if (af.getViewport().featuresDisplayed == null - || fr.renderOrder == null) + if (af.getViewport().isShowSequenceFeatures() || !fr.hasRenderOrder()) { fr.findAllFeatures(true); // display everything! } @@ -288,7 +286,7 @@ public class FeatureSettings extends JPanel public void actionPerformed(ActionEvent e) { - me.sortByScore(new String[] + me.af.avc.sortAlignmentByFeatureScore(new String[] { type }); } @@ -300,7 +298,7 @@ public class FeatureSettings extends JPanel public void actionPerformed(ActionEvent e) { - me.sortByDens(new String[] + me.af.avc.sortAlignmentByFeatureDensity(new String[] { type }); } @@ -424,10 +422,6 @@ public class FeatureSettings extends JPanel synchronized public void setTableData() { - if (fr.featureGroups == null) - { - fr.featureGroups = new Hashtable(); - } Vector allFeatures = new Vector(); Vector allGroups = new Vector(); SequenceFeature[] tmpfeatures; @@ -458,10 +452,7 @@ public class FeatureSettings extends JPanel if (!allGroups.contains(group)) { allGroups.addElement(group); - if (group != null) - { - checkGroupState(group); - } + checkGroupState(group); } } @@ -479,21 +470,14 @@ public class FeatureSettings extends JPanel } /** + * Synchronise gui group list and check visibility of group * * @param group - * @return true if group has been seen before and is already added to set. + * @return true if group is visible */ private boolean checkGroupState(String group) { - boolean visible; - if (fr.featureGroups.containsKey(group)) - { - visible = ((Boolean) fr.featureGroups.get(group)).booleanValue(); - } - else - { - visible = true; // new group is always made visible - } + boolean visible = fr.checkGroupVisibility(group, true); if (groupPanel == null) { @@ -514,10 +498,8 @@ public class FeatureSettings extends JPanel if (alreadyAdded) { - return true; + return visible; } - - fr.featureGroups.put(group, new Boolean(visible)); final String grp = group; final JCheckBox check = new JCheckBox(group, visible); check.setFont(new Font("Serif", Font.BOLD, 12)); @@ -525,8 +507,7 @@ public class FeatureSettings extends JPanel { public void itemStateChanged(ItemEvent evt) { - fr.featureGroups.put(check.getText(), - new Boolean(check.isSelected())); + fr.setGroupVisibility(check.getText(), check.isSelected()); af.alignPanel.getSeqPanel().seqCanvas.repaint(); if (af.alignPanel.overviewPanel != null) { @@ -538,7 +519,7 @@ public class FeatureSettings extends JPanel } }); groupPanel.add(check); - return false; + return visible; } boolean resettingTable = false; @@ -582,13 +563,8 @@ public class FeatureSettings extends JPanel continue; } - if (group == null || fr.featureGroups.get(group) == null - || ((Boolean) fr.featureGroups.get(group)).booleanValue()) + if (group == null || checkGroupState(group)) { - if (group != null) - { - checkGroupState(group); - } type = tmpfeatures[index].getType(); if (!visibleChecks.contains(type)) { @@ -623,19 +599,20 @@ public class FeatureSettings extends JPanel Object[][] data = new Object[fSize][3]; int dataIndex = 0; - if (fr.renderOrder != null) + if (fr.hasRenderOrder()) { if (!handlingUpdate) - { + { fr.findAllFeatures(groupChanged != null); // prod to update + // colourschemes. but don't + // affect display + // First add the checks in the previous render order, + // in case the window has been closed and reopened } - // colourschemes. but don't - // affect display - // First add the checks in the previous render order, - // in case the window has been closed and reopened - for (int ro = fr.renderOrder.length - 1; ro > -1; ro--) + List frl = fr.getRenderOrder(); + for (int ro = frl.size() - 1; ro > -1; ro--) { - type = fr.renderOrder[ro]; + type = frl.get(ro); if (!visibleChecks.contains(type)) { @@ -644,8 +621,8 @@ public class FeatureSettings extends JPanel data[dataIndex][0] = type; data[dataIndex][1] = fr.getFeatureStyle(type); - data[dataIndex][2] = new Boolean( - af.getViewport().featuresDisplayed.containsKey(type)); + data[dataIndex][2] = new Boolean(af.getViewport() + .getFeaturesDisplayed().isVisible(type)); dataIndex++; visibleChecks.removeElement(type); } @@ -663,7 +640,7 @@ public class FeatureSettings extends JPanel if (data[dataIndex][1] == null) { // "Colour has been updated in another view!!" - fr.renderOrder = null; + fr.clearRenderOrder(); return; } @@ -685,8 +662,8 @@ public class FeatureSettings extends JPanel if (groupPanel != null) { - groupPanel.setLayout(new GridLayout(fr.featureGroups.size() / 4 + 1, - 4)); + groupPanel.setLayout(new GridLayout( + fr.getFeatureGroupsSize() / 4 + 1, 4)); groupPanel.validate(); bigPanel.add(groupPanel, BorderLayout.NORTH); @@ -843,9 +820,10 @@ public class FeatureSettings extends JPanel PrintWriter out = new PrintWriter(new OutputStreamWriter( new FileOutputStream(choice), "UTF-8")); - Iterator e = fr.featureColours.keySet().iterator(); - float[] sortOrder = new float[fr.featureColours.size()]; - String[] sortTypes = new String[fr.featureColours.size()]; + Set fr_colours = fr.getAllFeatureColours(); + Iterator e = fr_colours.iterator(); + float[] sortOrder = new float[fr_colours.size()]; + String[] sortTypes = new String[fr_colours.size()]; int i = 0; while (e.hasNext()) { @@ -1068,7 +1046,7 @@ public class FeatureSettings extends JPanel { public void actionPerformed(ActionEvent e) { - sortByScore(null); + af.avc.sortAlignmentByFeatureScore(null); } }); sortByDens.setFont(JvSwingUtils.getLabelFont()); @@ -1078,7 +1056,22 @@ public class FeatureSettings extends JPanel { public void actionPerformed(ActionEvent e) { - sortByDens(null); + af.avc.sortAlignmentByFeatureDensity(null); + } + }); + help.setFont(JvSwingUtils.getLabelFont()); + help.setText(MessageManager.getString("action.help")); + help.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + try + { + Help.showHelpWindow(HelpId.SequenceFeatureSettings); + } catch (HelpSetException e1) + { + e1.printStackTrace(); + } } }); help.setFont(JvSwingUtils.getLabelFont()); @@ -1102,6 +1095,7 @@ public class FeatureSettings extends JPanel { public void actionPerformed(ActionEvent e) { + fr.setTransparency(originalTransparency); updateFeatureRenderer(originalData); close(); } @@ -1198,131 +1192,6 @@ public class FeatureSettings extends JPanel settingsPane.add(buttonPanel, java.awt.BorderLayout.SOUTH); } - protected void sortByDens(String[] typ) - { - sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY); - } - - protected void sortBy(String[] typ, String methodText, final String method) - { - if (typ == null) - { - typ = getDisplayedFeatureTypes(); - } - String gps[] = null; - gps = getDisplayedFeatureGroups(); - if (typ != null) - { - ArrayList types = new ArrayList(); - for (int i = 0; i < typ.length; i++) - { - if (typ[i] != null) - { - types.add(typ[i]); - } - typ = new String[types.size()]; - types.toArray(typ); - } - } - if (gps != null) - { - ArrayList grps = new ArrayList(); - - for (int i = 0; i < gps.length; i++) - { - if (gps[i] != null) - { - grps.add(gps[i]); - } - } - gps = new String[grps.size()]; - grps.toArray(gps); - } - AlignmentPanel alignPanel = af.alignPanel; - AlignmentI al = alignPanel.av.getAlignment(); - - int start, stop; - SequenceGroup sg = alignPanel.av.getSelectionGroup(); - if (sg != null) - { - start = sg.getStartRes(); - stop = sg.getEndRes(); - } - else - { - start = 0; - stop = al.getWidth(); - } - SequenceI[] oldOrder = al.getSequencesArray(); - AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method); - af.addHistoryItem(new OrderCommand(methodText, oldOrder, alignPanel.av - .getAlignment())); - alignPanel.paintAlignment(true); - - } - - protected void sortByScore(String[] typ) - { - sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE); - } - - private String[] getDisplayedFeatureTypes() - { - String[] typ = null; - if (fr != null) - { - synchronized (fr.renderOrder) - { - typ = new String[fr.renderOrder.length]; - System.arraycopy(fr.renderOrder, 0, typ, 0, typ.length); - for (int i = 0; i < typ.length; i++) - { - if (af.viewport.featuresDisplayed.get(typ[i]) == null) - { - typ[i] = null; - } - } - } - } - return typ; - } - - private String[] getDisplayedFeatureGroups() - { - String[] gps = null; - ArrayList _gps = new ArrayList(); - if (fr != null) - { - - if (fr.featureGroups != null) - { - Iterator en = fr.featureGroups.keySet().iterator(); - int g = 0; - boolean valid = false; - while (en.hasNext()) - { - String gp = (String) en.next(); - Boolean on = (Boolean) fr.featureGroups.get(gp); - if (on != null && on.booleanValue()) - { - valid = true; - _gps.add(gp); - } - } - if (!valid) - { - return null; - } - else - { - gps = new String[_gps.size()]; - _gps.toArray(gps); - } - } - } - return gps; - } - public void fetchDAS_actionPerformed(ActionEvent e) { fetchDAS.setEnabled(false); diff --git a/src/jalview/gui/Help.java b/src/jalview/gui/Help.java index ae3f457..b07cc4e 100644 --- a/src/jalview/gui/Help.java +++ b/src/jalview/gui/Help.java @@ -17,7 +17,8 @@ public class Help { public enum HelpId { - Home("home"), SequenceFeatureSettings("seqfeatures.settings"); + Home("home"), SequenceFeatureSettings("seqfeatures.settings"), StructureViewer( + "viewingpdbs"); private String id; diff --git a/src/jalview/gui/IdPanel.java b/src/jalview/gui/IdPanel.java index 3486f72..a22e918 100755 --- a/src/jalview/gui/IdPanel.java +++ b/src/jalview/gui/IdPanel.java @@ -111,7 +111,7 @@ public class IdPanel extends JPanel implements MouseListener, seqAnnotReport .createSequenceAnnotationReport(tip, sequence, av.isShowDbRefs(), av.isShowNpFeats(), - sp.seqCanvas.fr.minmax); + sp.seqCanvas.fr.getMinMax()); setToolTipText("" + sequence.getDisplayId(true) + " " + tip.toString() + ""); } diff --git a/src/jalview/gui/Jalview2XML.java b/src/jalview/gui/Jalview2XML.java index 8ddd050..5d11901 100644 --- a/src/jalview/gui/Jalview2XML.java +++ b/src/jalview/gui/Jalview2XML.java @@ -69,6 +69,8 @@ import jalview.util.MessageManager; import jalview.util.Platform; import jalview.util.jarInputStreamProvider; import jalview.viewmodel.AlignmentViewport; +import jalview.viewmodel.seqfeatures.FeatureRendererSettings; +import jalview.viewmodel.seqfeatures.FeaturesDisplayed; import jalview.ws.jws2.Jws2Discoverer; import jalview.ws.jws2.dm.AAConSettings; import jalview.ws.jws2.jabaws2.Jws2Instance; @@ -498,7 +500,7 @@ public class Jalview2XML for (String dssids : dsses.keySet()) { AlignFrame _af = dsses.get(dssids); - String jfileName = MessageManager.formatMessage("label.dataset_for", new String[]{fileName,_af.getTitle()}); + String jfileName = fileName + " Dataset for " + _af.getTitle(); if (!jfileName.endsWith(".xml")) { jfileName = jfileName + ".xml"; @@ -1128,7 +1130,7 @@ public class Jalview2XML view.setShowColourText(av.getColourText()); view.setShowFullId(av.getShowJVSuffix()); view.setRightAlignIds(av.isRightAlignIds()); - view.setShowSequenceFeatures(av.showSequenceFeatures); + view.setShowSequenceFeatures(av.isShowSequenceFeatures()); view.setShowText(av.getShowText()); view.setShowUnconserved(av.getShowUnconserved()); view.setWrapAlignment(av.getWrapAlignment()); @@ -1145,11 +1147,12 @@ public class Jalview2XML view.setFollowHighlight(av.followHighlight); view.setFollowSelection(av.followSelection); view.setIgnoreGapsinConsensus(av.getIgnoreGapsConsensus()); - if (av.featuresDisplayed != null) + if (av.getFeaturesDisplayed() != null) { jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings(); - String[] renderOrder = ap.getSeqPanel().seqCanvas.getFeatureRenderer().renderOrder; + String[] renderOrder = ap.getSeqPanel().seqCanvas.getFeatureRenderer() + .getRenderOrder().toArray(new String[0]); Vector settingsAdded = new Vector(); Object gstyle = null; @@ -1180,8 +1183,8 @@ public class Jalview2XML .getColour(renderOrder[ro]).getRGB()); } - setting.setDisplay(av.featuresDisplayed - .containsKey(renderOrder[ro])); + setting.setDisplay(av.getFeaturesDisplayed().isVisible( + renderOrder[ro])); float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer() .getOrder(renderOrder[ro]); if (rorder > -1) @@ -1194,8 +1197,8 @@ public class Jalview2XML } // Make sure we save none displayed feature settings - Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer().featureColours - .keySet().iterator(); + Iterator en = ap.getSeqPanel().seqCanvas.getFeatureRenderer() + .getFeatureColours().keySet().iterator(); while (en.hasNext()) { String key = en.next().toString(); @@ -1219,8 +1222,9 @@ public class Jalview2XML fs.addSetting(setting); settingsAdded.addElement(key); } - en = ap.getSeqPanel().seqCanvas.getFeatureRenderer().featureGroups - .keySet().iterator(); + // is groups actually supposed to be a map here ? + en = ap.getSeqPanel().seqCanvas.getFeatureRenderer().getFeatureGroups() + .iterator(); Vector groupsAdded = new Vector(); while (en.hasNext()) { @@ -1232,7 +1236,7 @@ public class Jalview2XML Group g = new Group(); g.setName(grp); g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas - .getFeatureRenderer().featureGroups.get(grp)) + .getFeatureRenderer().checkGroupVisibility(grp, false)) .booleanValue()); fs.addGroup(g); groupsAdded.addElement(grp); @@ -1429,6 +1433,7 @@ public class Jalview2XML an.addProperty(prop); } } + AnnotationElement ae; if (aa[i].annotations != null) { @@ -1456,8 +1461,7 @@ public class Jalview2XML } ae.setPosition(a); - if (aa[i].annotations[a].secondaryStructure != ' ' - && aa[i].annotations[a].secondaryStructure != '\0') + if (aa[i].annotations[a].secondaryStructure > ' ') { ae.setSecondaryStructure(aa[i].annotations[a].secondaryStructure + ""); @@ -2314,7 +2318,10 @@ public class Jalview2XML } else { - recoverDatasetFor(vamsasSet, al); + // recover dataset - passing on flag indicating if this a 'viewless' + // sequence set (a.k.a. a stored dataset for the project) + recoverDatasetFor(vamsasSet, al, object.getJalviewModelSequence() + .getViewportCount() == 0); } // /////////////////////////////// @@ -3534,10 +3541,8 @@ public class Jalview2XML af.viewport.setColourAppliesToAllGroups(true); - if (view.getShowSequenceFeatures()) - { - af.viewport.showSequenceFeatures = true; - } + af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures()); + if (view.hasCentreColumnLabels()) { af.viewport.setCentreColumnLabels(view.getCentreColumnLabels()); @@ -3604,9 +3609,14 @@ public class Jalview2XML // recover featre settings if (jms.getFeatureSettings() != null) { - af.viewport.featuresDisplayed = new Hashtable(); + FeaturesDisplayed fdi; + af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed()); String[] renderOrder = new String[jms.getFeatureSettings() .getSettingCount()]; + Hashtable featureGroups = new Hashtable(); + Hashtable featureColours = new Hashtable(); + Hashtable featureOrder = new Hashtable(); + for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++) { Setting setting = jms.getFeatureSettings().getSetting(fs); @@ -3633,41 +3643,42 @@ public class Jalview2XML gc.setColourByLabel(setting.getColourByLabel()); } // and put in the feature colour table. - af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setColour( - setting.getType(), gc); + featureColours.put(setting.getType(), gc); } else { - af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setColour( - setting.getType(), + featureColours.put(setting.getType(), new java.awt.Color(setting.getColour())); } renderOrder[fs] = setting.getType(); if (setting.hasOrder()) { - af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setOrder( - setting.getType(), setting.getOrder()); + featureOrder.put(setting.getType(), setting.getOrder()); } else { - af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setOrder( - setting.getType(), - fs / jms.getFeatureSettings().getSettingCount()); + featureOrder.put(setting.getType(), new Float(fs + / jms.getFeatureSettings().getSettingCount())); } if (setting.getDisplay()) { - af.viewport.featuresDisplayed.put(setting.getType(), new Integer( - setting.getColour())); + fdi.setVisible(setting.getType()); } } - af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().renderOrder = renderOrder; - Hashtable fgtable; - af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().featureGroups = fgtable = new Hashtable(); + Hashtable fgtable = new Hashtable(); for (int gs = 0; gs < jms.getFeatureSettings().getGroupCount(); gs++) { Group grp = jms.getFeatureSettings().getGroup(gs); fgtable.put(grp.getName(), new Boolean(grp.getDisplay())); } + // FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder, + // fgtable, featureColours, jms.getFeatureSettings().hasTransparency() ? + // jms.getFeatureSettings().getTransparency() : 0.0, featureOrder); + FeatureRendererSettings frs = new FeatureRendererSettings( + renderOrder, fgtable, featureColours, 1.0f, featureOrder); + af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer() + .transferSettings(frs); + } if (view.getHiddenColumnsCount() > 0) @@ -3986,7 +3997,8 @@ public class Jalview2XML } } - private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al) + private void recoverDatasetFor(SequenceSet vamsasSet, Alignment al, + boolean ignoreUnrefed) { jalview.datamodel.Alignment ds = getDatasetFor(vamsasSet.getDatasetId()); Vector dseqs = null; @@ -3998,7 +4010,7 @@ public class Jalview2XML for (int i = 0, iSize = vamsasSet.getSequenceCount(); i < iSize; i++) { Sequence vamsasSeq = vamsasSet.getSequence(i); - ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs); + ensureJalviewDatasetSequence(vamsasSeq, ds, dseqs, ignoreUnrefed); } // create a new dataset if (ds == null) @@ -4011,7 +4023,7 @@ public class Jalview2XML addDatasetRef(vamsasSet.getDatasetId(), ds); } // set the dataset for the newly imported alignment. - if (al.getDataset() == null) + if (al.getDataset() == null && !ignoreUnrefed) { al.setDataset(ds); } @@ -4027,7 +4039,7 @@ public class Jalview2XML * vector to add new dataset sequence to */ private void ensureJalviewDatasetSequence(Sequence vamsasSeq, - AlignmentI ds, Vector dseqs) + AlignmentI ds, Vector dseqs, boolean ignoreUnrefed) { // JBP TODO: Check this is called for AlCodonFrames to support recovery of // xRef Codon Maps @@ -4038,7 +4050,10 @@ public class Jalview2XML { dsq = sq.getDatasetSequence(); } - + if (sq == null && ignoreUnrefed) + { + return; + } String sqid = vamsasSeq.getDsseqid(); if (dsq == null) { @@ -4525,5 +4540,4 @@ public class Jalview2XML { skipList = skipList2; } - } diff --git a/src/jalview/gui/Jalview2XML_V1.java b/src/jalview/gui/Jalview2XML_V1.java index 9a58f51..586e2fa 100755 --- a/src/jalview/gui/Jalview2XML_V1.java +++ b/src/jalview/gui/Jalview2XML_V1.java @@ -40,6 +40,7 @@ import jalview.schemes.ResidueProperties; import jalview.structure.StructureSelectionManager; import jalview.util.MessageManager; import jalview.util.jarInputStreamProvider; +import jalview.viewmodel.seqfeatures.FeatureRendererSettings; import java.io.InputStreamReader; import java.util.Hashtable; @@ -411,29 +412,31 @@ public class Jalview2XML_V1 } af.viewport.setColourAppliesToAllGroups(true); - af.viewport.showSequenceFeatures = view.getShowSequenceFeatures(); + af.viewport.setShowSequenceFeatures(view.getShowSequenceFeatures()); if (jms.getFeatureSettings() != null) { - af.viewport.featuresDisplayed = new Hashtable(); + Hashtable featuresDisplayed = new Hashtable(); + Hashtable featureColours = new Hashtable(); String[] renderOrder = new String[jms.getFeatureSettings() .getSettingCount()]; for (int fs = 0; fs < jms.getFeatureSettings().getSettingCount(); fs++) { Setting setting = jms.getFeatureSettings().getSetting(fs); - af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().setColour( + featureColours.put( setting.getType(), new java.awt.Color(setting.getColour())); renderOrder[fs] = setting.getType(); if (setting.getDisplay()) { - af.viewport.featuresDisplayed.put(setting.getType(), new Integer( + featuresDisplayed.put(setting.getType(), new Integer( setting.getColour())); } } - af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().renderOrder = renderOrder; + FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder, new Hashtable(), featureColours, 1.0f, null); + af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer().transferSettings(frs); } af.setMenusFromViewport(af.viewport); diff --git a/src/jalview/gui/JalviewChimeraBindingModel.java b/src/jalview/gui/JalviewChimeraBindingModel.java index f68b585..ece8856 100644 --- a/src/jalview/gui/JalviewChimeraBindingModel.java +++ b/src/jalview/gui/JalviewChimeraBindingModel.java @@ -26,11 +26,11 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding { AlignmentPanel ap = (alignment == null) ? cvf.ap : (AlignmentPanel) alignment; - if (ap.av.showSequenceFeatures) + if (ap.av.isShowSequenceFeatures()) { if (fr == null) { - fr = ap.cloneFeatureRenderer(); + fr = (jalview.gui.FeatureRenderer) ap.cloneFeatureRenderer(); } else { @@ -71,7 +71,7 @@ public class JalviewChimeraBindingModel extends JalviewChimeraBinding } if (!isLoadingFromArchive()) { - colourBySequence(ap.av.getShowSequenceFeatures(), ap); + colourBySequence(ap.av.isShowSequenceFeatures(), ap); } } @Override diff --git a/src/jalview/gui/OverviewPanel.java b/src/jalview/gui/OverviewPanel.java index 95e14b4..5df60d2 100755 --- a/src/jalview/gui/OverviewPanel.java +++ b/src/jalview/gui/OverviewPanel.java @@ -67,7 +67,7 @@ public class OverviewPanel extends JPanel implements Runnable // main visible SeqCanvas SequenceRenderer sr; - FeatureRenderer fr; + jalview.renderer.seqfeatures.FeatureRenderer fr; /** * Creates a new OverviewPanel object. @@ -85,7 +85,7 @@ public class OverviewPanel extends JPanel implements Runnable sr.renderGaps = false; sr.forOverview = true; fr = new FeatureRenderer(ap); - + // scale the initial size of overviewpanel to shape of alignment float initialScale = (float) av.getAlignment().getWidth() / (float) av.getAlignment().getHeight(); @@ -254,7 +254,7 @@ public class OverviewPanel extends JPanel implements Runnable { miniMe = null; - if (av.showSequenceFeatures) + if (av.isShowSequenceFeatures()) { fr.transferSettings(ap.getSeqPanel().seqCanvas.getFeatureRenderer()); } @@ -344,7 +344,7 @@ public class OverviewPanel extends JPanel implements Runnable { color = sr.getResidueBoxColour(seq, lastcol).getRGB(); - if (av.showSequenceFeatures) + if (av.isShowSequenceFeatures()) { color = fr.findFeatureColour(color, seq, lastcol); } diff --git a/src/jalview/gui/PairwiseAlignPanel.java b/src/jalview/gui/PairwiseAlignPanel.java index 69b6ba6..bc2c27c 100755 --- a/src/jalview/gui/PairwiseAlignPanel.java +++ b/src/jalview/gui/PairwiseAlignPanel.java @@ -100,7 +100,7 @@ public class PairwiseAlignPanel extends GPairwiseAlignPanel textarea.append(as.getOutput()); sequences.add(as.getAlignedSeq1()); - sequences.add(as.getAlignedSeq1()); + sequences.add(as.getAlignedSeq2()); } } diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index 1a7235f..3ea689f 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -27,6 +27,7 @@ import jalview.commands.ChangeCaseCommand; import jalview.commands.EditCommand; import jalview.commands.EditCommand.Action; import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentI; import jalview.datamodel.Annotation; import jalview.datamodel.DBRefEntry; import jalview.datamodel.PDBEntry; @@ -1765,12 +1766,13 @@ public class PopupMenu extends JPopupMenu /** * Check for any annotations on the underlying dataset sequences (for the - * current selection group) which are not on the alignment annotations for the - * sequence. If any are found, enable the option to add them to the alignment. - * The criteria for 'on the alignment' is finding an alignment annotation on - * the sequence, that matches on calcId and label. A tooltip is also - * constructed that displays the source (calcId) and type (label) of the - * annotations that can be added. + * current selection group) which are not 'on the alignment'.If any are found, + * enable the option to add them to the alignment. The criteria for 'on the + * alignment' is finding an alignment annotation on the alignment, matched on + * calcId, label and sequenceRef. + * + * A tooltip is also constructed that displays the source (calcId) and type + * (label) of the annotations that can be added. * * @param menuItem * @param forSequences @@ -1797,10 +1799,11 @@ public class PopupMenu extends JPopupMenu /* * For each sequence selected in the alignment, make a list of any * annotations on the underlying dataset sequence which are not already on - * the sequence in the alignment. + * the alignment. * * Build a map of { alignmentSequence, } */ + AlignmentI al = this.ap.av.getAlignment(); final Map> candidates = new LinkedHashMap>(); for (SequenceI seq : forSequences) { @@ -1818,11 +1821,12 @@ public class PopupMenu extends JPopupMenu for (AlignmentAnnotation dsann : datasetAnnotations) { /* - * If the sequence has no annotation that matches this one, then add - * this one to the results list. + * Find matching annotations on the alignment. */ - if (seq.getAlignmentAnnotations(dsann.getCalcId(), dsann.label) - .isEmpty()) + final Iterable matchedAlignmentAnnotations = al + .findAnnotations(seq, dsann.getCalcId(), + dsann.label); + if (!matchedAlignmentAnnotations.iterator().hasNext()) { result.add(dsann); tipEntries.put(dsann.getCalcId(), dsann.label); @@ -1891,8 +1895,14 @@ public class PopupMenu extends JPopupMenu } copyAnn.restrict(startRes, endRes); - // add to the sequence (sets copyAnn.datasetSequence) - seq.addAlignmentAnnotation(copyAnn); + /* + * Add to the sequence (sets copyAnn.datasetSequence), unless the + * original annotation is already on the sequence. + */ + if (!seq.hasAnnotation(ann)) + { + seq.addAlignmentAnnotation(copyAnn); + } // adjust for gaps copyAnn.adjustForAlignment(); // add to the alignment and set visible @@ -1933,7 +1943,9 @@ public class PopupMenu extends JPopupMenu true, true, false, - (ap.getSeqPanel().seqCanvas.fr != null) ? ap.getSeqPanel().seqCanvas.fr.minmax + (ap.getSeqPanel().seqCanvas.fr != null) ? ap + .getSeqPanel().seqCanvas.fr + .getMinMax() : null); contents.append("

    "); } diff --git a/src/jalview/gui/Preferences.java b/src/jalview/gui/Preferences.java index b082bc6..bdc83e5 100755 --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@ -22,6 +22,7 @@ package jalview.gui; import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder; import jalview.bin.Cache; +import jalview.gui.Help.HelpId; import jalview.gui.StructureViewer.Viewer; import jalview.io.JalviewFileChooser; import jalview.io.JalviewFileView; @@ -39,15 +40,19 @@ import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.io.File; import java.util.Collection; +import java.util.List; import java.util.StringTokenizer; import java.util.Vector; +import javax.help.HelpSetException; import javax.swing.JColorChooser; import javax.swing.JFileChooser; import javax.swing.JInternalFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; +import ext.edu.ucsf.rbvi.strucviz2.StructureManager; + /** * DOCUMENT ME! * @@ -596,7 +601,8 @@ public class Preferences extends GPreferences } /** - * Do any necessary validation before saving settings. + * Do any necessary validation before saving settings. Return focus to the + * first tab which fails validation. * * @return */ @@ -879,4 +885,53 @@ public class Preferences extends GPreferences return true; } + /** + * If Chimera is selected, check it can be found on default or user-specified + * path, if not show a warning/help dialog. + */ + @Override + protected void structureViewer_actionPerformed(String selectedItem) + { + if (!selectedItem.equals(Viewer.CHIMERA.name())) + { + return; + } + boolean found = false; + + /* + * Try user-specified and standard paths for Chimera executable. + */ + List paths = StructureManager.getChimeraPaths(); + paths.add(0, chimeraPath.getText()); + for (String path : paths) + { + if (new File(path.trim()).canExecute()) + { + found = true; + break; + } + } + if (!found) + { + String[] options = + { "OK", "Help" }; + int showHelp = JOptionPane.showInternalOptionDialog( + Desktop.desktop, + JvSwingUtils.wrapTooltip(true, + MessageManager.getString("label.chimera_missing")), + "", JOptionPane.YES_NO_OPTION, + JOptionPane.WARNING_MESSAGE, null, options, options[0]); + if (showHelp == JOptionPane.NO_OPTION) + { + try + { + Help.showHelpWindow(HelpId.StructureViewer); + } catch (HelpSetException e) + { + e.printStackTrace(); + } + } + } + } + } diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index 54abcc2..4d1546b 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -711,7 +711,7 @@ public class SeqCanvas extends JComponent sr.drawSequence(nextSeq, av.getAlignment().findAllGroups(nextSeq), startRes, endRes, offset + ((i - startSeq) * av.charHeight)); - if (av.showSequenceFeatures) + if (av.isShowSequenceFeatures()) { fr.drawSequence(g, nextSeq, startRes, endRes, offset + ((i - startSeq) * av.charHeight)); diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java index de1ffdf..7c6a202 100644 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@ -243,44 +243,6 @@ public class SeqPanel extends JPanel implements MouseListener, return seq; } - SequenceFeature[] findFeaturesAtRes(SequenceI sequence, int res) - { - Vector tmp = new Vector(); - SequenceFeature[] features = sequence.getSequenceFeatures(); - if (features != null) - { - for (int i = 0; i < features.length; i++) - { - if (av.featuresDisplayed == null - || !av.featuresDisplayed.containsKey(features[i].getType())) - { - continue; - } - - if (features[i].featureGroup != null - && seqCanvas.fr.featureGroups != null - && seqCanvas.fr.featureGroups - .containsKey(features[i].featureGroup) - && !((Boolean) seqCanvas.fr.featureGroups - .get(features[i].featureGroup)).booleanValue()) - { - continue; - } - - if ((features[i].getBegin() <= res) - && (features[i].getEnd() >= res)) - { - tmp.addElement(features[i]); - } - } - } - - features = new SequenceFeature[tmp.size()]; - tmp.copyInto(features); - - return features; - } - void endEditing() { if (editCommand != null && editCommand.getSize() > 0) @@ -743,14 +705,14 @@ public class SeqPanel extends JPanel implements MouseListener, } // use aa to see if the mouse pointer is on a - if (av.showSequenceFeatures) + if (av.isShowSequenceFeatures()) { int rpos; - SequenceFeature[] features = findFeaturesAtRes( + List features = ap.getFeatureRenderer().findFeaturesAtRes( sequence.getDatasetSequence(), rpos = sequence.findPosition(res)); seqARep.appendFeatures(tooltipText, rpos, features, - this.ap.getSeqPanel().seqCanvas.fr.minmax); + this.ap.getSeqPanel().seqCanvas.fr.getMinMax()); } if (tooltipText.length() == 6) // { @@ -1389,21 +1351,21 @@ public class SeqPanel extends JPanel implements MouseListener, av.setSelectionGroup(null); } - SequenceFeature[] features = findFeaturesAtRes( + List features = seqCanvas.getFeatureRenderer().findFeaturesAtRes( sequence.getDatasetSequence(), sequence.findPosition(findRes(evt))); - if (features != null && features.length > 0) + if (features != null && features.size()> 0) { SearchResults highlight = new SearchResults(); - highlight.addResult(sequence, features[0].getBegin(), - features[0].getEnd()); + highlight.addResult(sequence, features.get(0).getBegin(), + features.get(0).getEnd()); seqCanvas.highlightSearchResults(highlight); } - if (features != null && features.length > 0) + if (features != null && features.size()> 0) { seqCanvas.getFeatureRenderer().amendFeatures(new SequenceI[] - { sequence }, features, false, ap); + { sequence }, features.toArray(new SequenceFeature[features.size()]), false, ap); seqCanvas.highlightSearchResults(null); } @@ -1518,16 +1480,16 @@ public class SeqPanel extends JPanel implements MouseListener, if (javax.swing.SwingUtilities.isRightMouseButton(evt)) { - SequenceFeature[] allFeatures = findFeaturesAtRes( + List allFeatures = ap.getFeatureRenderer().findFeaturesAtRes( sequence.getDatasetSequence(), sequence.findPosition(res)); Vector links = new Vector(); - for (int i = 0; i < allFeatures.length; i++) + for (SequenceFeature sf:allFeatures) { - if (allFeatures[i].links != null) + if (sf.links != null) { - for (int j = 0; j < allFeatures[i].links.size(); j++) + for (int j = 0; j < sf.links.size(); j++) { - links.addElement(allFeatures[i].links.elementAt(j)); + links.addElement(sf.links.elementAt(j)); } } } diff --git a/src/jalview/gui/SequenceRenderer.java b/src/jalview/gui/SequenceRenderer.java index bcbebbd..177fc83 100755 --- a/src/jalview/gui/SequenceRenderer.java +++ b/src/jalview/gui/SequenceRenderer.java @@ -20,6 +20,7 @@ */ package jalview.gui; +import jalview.api.FeatureRenderer; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; @@ -80,11 +81,12 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer // If EPS graphics, stringWidth will be a double, not an int double dwidth = fm.getStringBounds("M", g).getWidth(); - monospacedFont = (dwidth == fm.getStringBounds("|", g).getWidth() && (float) av.charWidth == dwidth); + monospacedFont = (dwidth == fm.getStringBounds("|", g).getWidth() && av.charWidth == dwidth); this.renderGaps = renderGaps; } + @Override public Color getResidueBoxColour(SequenceI seq, int i) { allGroups = av.getAlignment().findAllGroups(seq); @@ -105,6 +107,31 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer } /** + * Get the residue colour at the given sequence position - as determined by + * the sequence group colour (if any), else the colour scheme, possibly + * overridden by a feature colour. + * + * @param seq + * @param position + * @param fr + * @return + */ + @Override + public Color getResidueColour(final SequenceI seq, int position, + FeatureRenderer fr) + { + // TODO replace 8 or so code duplications with calls to this method + // (refactored as needed) + Color col = getResidueBoxColour(seq, position); + + if (fr != null) + { + col = fr.findFeatureColour(col, seq, position); + } + return col; + } + + /** * DOCUMENT ME! * * @param cs @@ -188,7 +215,9 @@ public class SequenceRenderer implements jalview.api.SequenceRenderer int y1) { if (seq == null) + { return; // fix for racecondition + } int i = start; int length = seq.getLength(); diff --git a/src/jalview/gui/TreePanel.java b/src/jalview/gui/TreePanel.java index ee0bfaf..6ce68b3 100755 --- a/src/jalview/gui/TreePanel.java +++ b/src/jalview/gui/TreePanel.java @@ -20,27 +20,47 @@ */ package jalview.gui; -import java.beans.*; -import java.io.*; -import java.util.*; -import java.util.List; - -import javax.imageio.*; - -import java.awt.*; -import java.awt.event.*; -import java.awt.image.*; -import javax.swing.*; - -import org.jibble.epsgraphics.*; -import jalview.analysis.*; +import jalview.analysis.AlignmentSorter; +import jalview.analysis.NJTree; +import jalview.api.analysis.ScoreModelI; +import jalview.api.analysis.ViewBasedAnalysisI; +import jalview.bin.Cache; import jalview.commands.CommandI; import jalview.commands.OrderCommand; -import jalview.datamodel.*; -import jalview.io.*; -import jalview.jbgui.*; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.AlignmentView; +import jalview.datamodel.BinaryNode; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.NodeTransformI; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.datamodel.SequenceNode; +import jalview.io.JalviewFileChooser; +import jalview.io.JalviewFileView; +import jalview.io.NewickFile; +import jalview.jbgui.GTreePanel; +import jalview.schemes.ResidueProperties; import jalview.util.MessageManager; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.beans.PropertyChangeEvent; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.imageio.ImageIO; +import javax.swing.ButtonGroup; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; + +import org.jibble.epsgraphics.EpsGraphics2D; + /** * DOCUMENT ME! * @@ -293,8 +313,26 @@ public class TreePanel extends GTreePanel seqs = av.getSelectionGroup().getSequencesInOrder( av.getAlignment()); } - - tree = new NJTree(seqs, seqStrings, type, pwtype, start, end); + ScoreModelI sm = ResidueProperties.getScoreModel(pwtype); + if (sm instanceof ViewBasedAnalysisI) + { + try + { + sm = sm.getClass().newInstance(); + ((ViewBasedAnalysisI) sm) + .configureFromAlignmentView(treeCanvas.ap); + } catch (Exception q) + { + Cache.log.error("Couldn't create a scoremodel instance for " + + sm.getName()); + } + tree = new NJTree(seqs, seqStrings, type, pwtype, sm, start, end); + } + else + { + tree = new NJTree(seqs, seqStrings, type, pwtype, null, start, + end); + } showDistances(true); } diff --git a/src/jalview/gui/WebserviceInfo.java b/src/jalview/gui/WebserviceInfo.java index 8dcf72a..cd93277 100644 --- a/src/jalview/gui/WebserviceInfo.java +++ b/src/jalview/gui/WebserviceInfo.java @@ -20,21 +20,40 @@ */ package jalview.gui; -import java.util.*; +import jalview.jbgui.GWebserviceInfo; +import jalview.util.MessageManager; +import jalview.ws.WSClientI; -import java.awt.*; -import java.awt.event.*; -import java.awt.image.*; -import javax.swing.*; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.MediaTracker; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.util.Hashtable; +import java.util.Vector; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JEditorPane; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; -import jalview.jbgui.*; -import jalview.util.MessageManager; -import jalview.ws.WSClientI; - /** * Base class for web service client thread and gui TODO: create StAX parser to * extract html body content reliably when preparing html formatted job statuses @@ -78,6 +97,13 @@ public class WebserviceInfo extends GWebserviceInfo implements JInternalFrame frame; + @Override + public void setVisible(boolean aFlag) + { + super.setVisible(aFlag); + frame.setVisible(aFlag); + }; + JTabbedPane subjobs = null; java.util.Vector jobPanes = null; @@ -210,10 +236,13 @@ public class WebserviceInfo extends GWebserviceInfo implements * short name and job type * @param info * reference or other human readable description + * @param makeVisible + * true to display the webservices window immediatly (otherwise need + * to call setVisible(true)) */ - public WebserviceInfo(String title, String info) + public WebserviceInfo(String title, String info, boolean makeVisible) { - init(title, info, 520, 500); + init(title, info, 520, 500, makeVisible); } /** @@ -228,9 +257,10 @@ public class WebserviceInfo extends GWebserviceInfo implements * @param height * DOCUMENT ME! */ - public WebserviceInfo(String title, String info, int width, int height) + public WebserviceInfo(String title, String info, int width, int height, + boolean makeVisible) { - init(title, info, width, height); + init(title, info, width, height, makeVisible); } /** @@ -288,11 +318,12 @@ public class WebserviceInfo extends GWebserviceInfo implements * @param height * DOCUMENT ME! */ - void init(String title, String info, int width, int height) + void init(String title, String info, int width, int height, + boolean makeVisible) { frame = new JInternalFrame(); frame.setContentPane(this); - Desktop.addInternalFrame(frame, title, width, height); + Desktop.addInternalFrame(frame, title, makeVisible, width, height); frame.setClosable(false); this.title = title; diff --git a/src/jalview/gui/WsParamSetManager.java b/src/jalview/gui/WsParamSetManager.java index 3322d6a..2db19a2 100644 --- a/src/jalview/gui/WsParamSetManager.java +++ b/src/jalview/gui/WsParamSetManager.java @@ -20,6 +20,13 @@ */ package jalview.gui; +import jalview.bin.Cache; +import jalview.io.JalviewFileChooser; +import jalview.util.MessageManager; +import jalview.ws.params.ParamDatastoreI; +import jalview.ws.params.ParamManager; +import jalview.ws.params.WsParamSetI; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -33,13 +40,6 @@ import java.util.StringTokenizer; import javax.swing.JOptionPane; -import jalview.bin.Cache; -import jalview.io.JalviewFileChooser; -import jalview.util.MessageManager; -import jalview.ws.params.ParamDatastoreI; -import jalview.ws.params.ParamManager; -import jalview.ws.params.WsParamSetI; - /** * store and retrieve web service parameter sets. * @@ -159,7 +159,7 @@ public class WsParamSetManager implements ParamManager { if (filename != null && !((outfile = new File(filename)).canWrite())) { - Cache.log.info("Can't write to " + filename + Cache.log.warn("Can't write to " + filename + " - Prompting for new file to write to."); filename = null; } diff --git a/src/jalview/io/AppletFormatAdapter.java b/src/jalview/io/AppletFormatAdapter.java index d3b19fa..505f609 100755 --- a/src/jalview/io/AppletFormatAdapter.java +++ b/src/jalview/io/AppletFormatAdapter.java @@ -47,7 +47,9 @@ public class AppletFormatAdapter */ public static final String[] READABLE_FORMATS = new String[] { "BLC", "CLUSTAL", "FASTA", "MSF", "PileUp", "PIR", "PFAM", "STH", - "PDB", "JnetFile", "RNAML", PhylipFile.FILE_DESC }; // , "SimpleBLAST" }; + "PDB", "JnetFile", "RNAML", PhylipFile.FILE_DESC, "HTML" }; // , + // "SimpleBLAST" + // }; /** * List of valid format strings for use by callers of the formatSequences @@ -79,7 +81,8 @@ public class AppletFormatAdapter */ public static final String[] READABLE_EXTENSIONS = new String[] { "fa, fasta, mfa, fastq", "aln", "pfam", "msf", "pir", "blc", "amsa", - "jar,jvp", "sto,stk", "xml,rnaml", PhylipFile.FILE_EXT }; // ".blast" + "jar,jvp", "sto,stk", "xml,rnaml", PhylipFile.FILE_EXT, + "html" }; // ".blast" /** * List of readable formats by application in order corresponding to @@ -87,7 +90,7 @@ public class AppletFormatAdapter */ public static final String[] READABLE_FNAMES = new String[] { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "AMSA", "Jalview", - "Stockholm", "RNAML", PhylipFile.FILE_DESC };// , + "Stockholm", "RNAML", PhylipFile.FILE_DESC, "HTML" };// , // "SimpleBLAST" // }; @@ -109,7 +112,7 @@ public class AppletFormatAdapter for (int i = 0, iSize = els.length - 1; i < iSize; i++) { list.append(els[i]); - list.append(","); + list.append(", "); } list.append(" and " + els[els.length - 1] + "."); return list.toString(); @@ -268,6 +271,10 @@ public class AppletFormatAdapter { afile = new PhylipFile(inFile, type); } + // else if (format.equals(HtmlFile.FILE_DESC)) + // { + // afile = new HtmlFile(inFile, type); + // } else if (format.equals("RNAML")) { afile = new RnamlFile(inFile, type); @@ -392,6 +399,10 @@ public class AppletFormatAdapter { afile = new PhylipFile(source); } + // else if (format.equals(HtmlFile.FILE_DESC)) + // { + // afile = new HtmlFile(source); + // } Alignment al = new Alignment(afile.getSeqsAsArray()); afile.addAnnotations(al); @@ -527,6 +538,10 @@ public class AppletFormatAdapter { afile = new PhylipFile(); } + // else if (format.equalsIgnoreCase(HtmlFile.FILE_DESC)) + // { + // afile = new HtmlFile(); + // } else if (format.equalsIgnoreCase("RNAML")) { afile = new RnamlFile(); diff --git a/src/jalview/io/BioJsHTMLOutput.java b/src/jalview/io/BioJsHTMLOutput.java new file mode 100644 index 0000000..db43a3f --- /dev/null +++ b/src/jalview/io/BioJsHTMLOutput.java @@ -0,0 +1,222 @@ +package jalview.io; + +import jalview.api.FeaturesDisplayedI; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.exceptions.NoFileSelectedException; +import jalview.gui.AlignViewport; +import jalview.gui.AlignmentPanel; +import jalview.gui.FeatureRenderer; +import jalview.json.binding.v1.BioJsAlignmentPojo; +import jalview.json.binding.v1.BioJsFeaturePojo; +import jalview.json.binding.v1.BioJsSeqPojo; +import jalview.schemes.ColourSchemeProperty; +import jalview.util.MessageManager; + +import java.awt.Color; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.URL; +import java.util.ArrayList; + +import com.json.JSONException; + +public class BioJsHTMLOutput +{ + private AlignViewport av; + + private jalview.api.FeatureRenderer fr; + + private String globalColorScheme; + + private FeaturesDisplayedI displayedFeatures; + + private String jalviewVersion; + + private String webStartLaunchServletUrl = "http://www.jalview.org/services/launchApp"; + + public BioJsHTMLOutput(AlignmentPanel ap, + FeatureRenderer fr1) + { + + jalviewVersion = jalview.bin.Cache.getProperty("VERSION"); + webStartLaunchServletUrl = jalview.bin.Cache.getDefault( + "www.jalview.org", "http://www.jalview.org") + + "/services/launchApp"; + if (ap != null) + { + this.av = ap.av; + this.globalColorScheme = ColourSchemeProperty.getColourName(av + .getGlobalColourScheme()); + this.fr = ap.cloneFeatureRenderer(); + displayedFeatures = av.getFeaturesDisplayed(); + } + } + + private void exportJalviewAlignmentAsBioJsHtmlFile() + { + try + { + String outputFile = getOutputFile(); + String jalviewAlignmentJson = getJalviewAlignmentAsJsonString(av + .getAlignment()); + String bioJSTemplateString = getBioJsTemplateAsString(this); + String generatedBioJsWithJalviewAlignmentAsJson = bioJSTemplateString + .replaceAll( +"#sequenceData#", jalviewAlignmentJson) + .toString(); + + PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter( + outputFile)); + out.print(generatedBioJsWithJalviewAlignmentAsJson); + out.flush(); + out.close(); + jalview.util.BrowserLauncher.openURL("file:///" + outputFile); + } catch (NoFileSelectedException ex) + { + // do noting if no file was selected + } catch (Exception e) + { + e.printStackTrace(); + } + } + + public String getOutputFile() throws NoFileSelectedException + { + String selectedFile = null; + JalviewFileChooser jvFileChooser = new JalviewFileChooser( + jalview.bin.Cache.getProperty("LAST_DIRECTORY"), new String[] + { "html" }, new String[] + { "HTML files" }, "HTML files"); + jvFileChooser.setFileView(new JalviewFileView()); + + // TODO uncomment when supported by MassageManager + jvFileChooser.setDialogTitle(MessageManager + .getString("label.save_as_biojs_html")); + jvFileChooser.setDialogTitle("save as BioJs HTML"); + jvFileChooser.setToolTipText(MessageManager.getString("action.save")); + + int fileChooserOpt = jvFileChooser.showSaveDialog(null); + if (fileChooserOpt == JalviewFileChooser.APPROVE_OPTION) + { + jalview.bin.Cache.setProperty("LAST_DIRECTORY", jvFileChooser + .getSelectedFile().getParent()); + selectedFile = jvFileChooser.getSelectedFile().getPath(); + } + else + { + throw new NoFileSelectedException("No file was selected."); + } + + return selectedFile; + } + + public String getJalviewAlignmentAsJsonString(AlignmentI alignment) + throws IOException, JSONException + { + BioJsAlignmentPojo bjsAlignment = new BioJsAlignmentPojo(); + + bjsAlignment.setGlobalColorScheme(getGlobalColorScheme()); + bjsAlignment.setJalviewVersion(jalviewVersion); + bjsAlignment.setWebStartUrl(webStartLaunchServletUrl); + + int count = 0; + for (SequenceI seq : alignment.getSequences()) + { + StringBuilder name = new StringBuilder(); + name.append(seq.getName()).append("/").append(seq.getStart()) + .append("-").append(seq.getEnd()); + + BioJsSeqPojo seqPojo = new BioJsSeqPojo(); + seqPojo.setId(String.valueOf(++count)); + seqPojo.setEnd(seq.getEnd()); + seqPojo.setStart(seq.getStart()); + seqPojo.setName(name.toString()); + seqPojo.setSeq(seq.getSequenceAsString()); + + SequenceFeature[] seqFeatures = seq.getDatasetSequence() + .getSequenceFeatures(); + if (seqFeatures != null) + { + ArrayList bjsSeqFeatures = new ArrayList(); + for (SequenceFeature sf : seqFeatures) + { + if (displayedFeatures != null + && displayedFeatures.isVisible(sf.getType())) + { + + // TODO: translate graduated/complex colourschemes to biojs model + String featureColour = jalview.util.Format.getHexString(fr + .findFeatureColour(Color.white, seq, + seq.findIndex(sf.getBegin()))); + BioJsFeaturePojo bjsFeature = new BioJsFeaturePojo(); + bjsFeature.setFillColor(featureColour); + bjsFeature.setXstart(seq.findIndex(sf.getBegin()) - 1); + bjsFeature.setXend(seq.findIndex(sf.getEnd())); + bjsFeature.setText(sf.getType()); + bjsSeqFeatures.add(bjsFeature); + } + } + seqPojo.setFeatures(bjsSeqFeatures); + } + bjsAlignment.getSeqs().add(seqPojo); + } + + return new com.json.JSONObject(bjsAlignment).toString() + .replaceAll("xstart", "xStart").replaceAll("xend", "xEnd"); + } + + public static String getBioJsTemplateAsString(Object currentObj) + throws IOException + { + InputStreamReader isReader = null; + BufferedReader buffReader = null; + StringBuilder sb = new StringBuilder(); + URL url = currentObj.getClass().getResource( + "/templates/BioJSTemplate.txt"); + if (url != null) + { + try + { + isReader = new InputStreamReader(url.openStream()); + buffReader = new BufferedReader(isReader); + String line; + String lineSeparator = System.getProperty("line.separator"); + while ((line = buffReader.readLine()) != null) + { + sb.append(line).append(lineSeparator); + } + + } catch (Exception ex) + { + ex.printStackTrace(); + } finally + { + if (isReader != null) + { + isReader.close(); + } + + if (buffReader != null) + { + buffReader.close(); + } + } + } + return sb.toString(); + } + + public String getGlobalColorScheme() + { + return globalColorScheme; + } + + public void setGlobalColorScheme(String globalColorScheme) + { + this.globalColorScheme = globalColorScheme; + } + +} diff --git a/src/jalview/io/FeaturesFile.java b/src/jalview/io/FeaturesFile.java index 87b829f..5b621e7 100755 --- a/src/jalview/io/FeaturesFile.java +++ b/src/jalview/io/FeaturesFile.java @@ -678,7 +678,7 @@ public class FeaturesFile extends AlignFile * hash of feature types and colours * @return features file contents */ - public String printJalviewFormat(SequenceI[] seqs, Hashtable visible) + public String printJalviewFormat(SequenceI[] seqs, Map visible) { return printJalviewFormat(seqs, visible, true, true); } @@ -697,7 +697,7 @@ public class FeaturesFile extends AlignFile * of group or type) * @return features file contents */ - public String printJalviewFormat(SequenceI[] seqs, Hashtable visible, + public String printJalviewFormat(SequenceI[] seqs, Map visible, boolean visOnly, boolean nonpos) { StringBuffer out = new StringBuffer(); @@ -714,11 +714,11 @@ public class FeaturesFile extends AlignFile // write feature colours only if we're given them and we are generating // viewed features // TODO: decide if feature links should also be written here ? - Enumeration en = visible.keys(); + Iterator en = visible.keySet().iterator(); String type, color; - while (en.hasMoreElements()) + while (en.hasNext()) { - type = en.nextElement().toString(); + type = en.next().toString(); if (visible.get(type) instanceof GraduatedColor) { @@ -926,12 +926,12 @@ public class FeaturesFile extends AlignFile * @param visible * @return */ - public String printGFFFormat(SequenceI[] seqs, Hashtable visible) + public String printGFFFormat(SequenceI[] seqs, Map visible) { return printGFFFormat(seqs, visible, true, true); } - public String printGFFFormat(SequenceI[] seqs, Hashtable visible, + public String printGFFFormat(SequenceI[] seqs, Map visible, boolean visOnly, boolean nonpos) { StringBuffer out = new StringBuffer(); diff --git a/src/jalview/io/FileLoader.java b/src/jalview/io/FileLoader.java index 82b94c3..833f590 100755 --- a/src/jalview/io/FileLoader.java +++ b/src/jalview/io/FileLoader.java @@ -152,6 +152,7 @@ public class FileLoader implements Runnable public AlignFrame LoadFileWaitTillLoaded(FileParse source, String format) { this.source = source; + file = source.getInFile(); protocol = source.type; this.format = format; @@ -352,6 +353,11 @@ public class FileLoader implements Runnable { alignFrame.setFileName(file, format); } + if (source instanceof HtmlFile) + { + ((HtmlFile) source).LoadAlignmentFeatures(alignFrame); + + } if (raiseGUI) { // add the window to the GUI diff --git a/src/jalview/io/FormatAdapter.java b/src/jalview/io/FormatAdapter.java index 8ca0c35..df5353c 100755 --- a/src/jalview/io/FormatAdapter.java +++ b/src/jalview/io/FormatAdapter.java @@ -255,6 +255,41 @@ public class FormatAdapter extends AppletFormatAdapter return this.formatSequences(format, alignment, suffix); } + public Alignment readFile(String inFile, String type, String format) + throws java.io.IOException + { + Alignment al; + if (format.equals("HTML")) + { + afile = new HtmlFile(inFile, type); + al = new Alignment(afile.getSeqsAsArray()); + afile.addAnnotations(al); + } + else + { + al = super.readFile(inFile, type, format); + } + + return al; + } + + public AlignmentI readFromFile(FileParse source, String format) + throws java.io.IOException + { + Alignment al; + if (format.equals("HTML")) + { + afile = new HtmlFile(source); + al = new Alignment(afile.getSeqsAsArray()); + afile.addAnnotations(al); + } + else + { + al = (Alignment) super.readFromFile(source, format); + } + return al; + } + /** * validate format is valid for IO in Application. This is basically the * AppletFormatAdapter.isValidFormat call with additional checks for diff --git a/src/jalview/io/HTMLOutput.java b/src/jalview/io/HTMLOutput.java index 50b07e4..2d2626f 100755 --- a/src/jalview/io/HTMLOutput.java +++ b/src/jalview/io/HTMLOutput.java @@ -34,7 +34,7 @@ public class HTMLOutput SequenceRenderer sr; - FeatureRenderer fr; + jalview.renderer.seqfeatures.FeatureRenderer fr; Color color; diff --git a/src/jalview/io/HtmlFile.java b/src/jalview/io/HtmlFile.java new file mode 100644 index 0000000..3cb7c3f --- /dev/null +++ b/src/jalview/io/HtmlFile.java @@ -0,0 +1,152 @@ +package jalview.io; + +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceFeature; +import jalview.gui.AlignFrame; +import jalview.json.binding.v1.BioJsAlignmentPojo.JalviewBioJsColorSchemeMapper; +import jalview.schemes.ColourSchemeI; + +import java.io.IOException; +import java.util.Iterator; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +public class HtmlFile extends AlignFile +{ + // public static final String FILE_EXT = "html"; + // + // public static final String FILE_DESC = "HTML"; + + private ColourSchemeI cs; + + public HtmlFile() + { + super(); + } + + public HtmlFile(FileParse source) throws IOException + { + super(source); + } + + public HtmlFile(String inFile, String type) throws IOException + { + super(inFile, type); + } + + @SuppressWarnings("unchecked") + @Override + public void parse() throws IOException + { + try + { + StringBuilder htmlData = new StringBuilder(); + String currentLine; + while ((currentLine = nextLine()) != null) + { + htmlData.append(currentLine); + } + + Document doc = Jsoup.parse(htmlData.toString()); + Element content = doc.getElementById("seqData"); + + String alignmentJsonString = content.val(); + JSONParser jsonParser = new JSONParser(); + JSONObject alignmentJsonObj = (JSONObject) jsonParser + .parse(alignmentJsonString); + JSONArray seqJsonArray = (JSONArray) alignmentJsonObj.get("seqs"); + String bioJsColourScheme = (String) alignmentJsonObj + .get("globalColorScheme"); + cs = getJalviewColorScheme(bioJsColourScheme); + + for (Iterator sequenceIter = seqJsonArray.iterator(); sequenceIter + .hasNext();) + { + JSONObject sequence = sequenceIter.next(); + String sequcenceString = sequence.get("seq").toString(); + Sequence seq = new Sequence(sequence.get("name").toString(), + sequcenceString, Integer.valueOf(sequence.get("start") + .toString()), Integer.valueOf(sequence.get("end") + .toString())); + + JSONArray jsonSeqArray = (JSONArray) sequence.get("features"); + SequenceFeature[] retrievedSeqFeatures = getJalviewSequenceFeatures( + jsonSeqArray, seq); + if (retrievedSeqFeatures != null) + { + seq.setSequenceFeatures(retrievedSeqFeatures); + } + seqs.add(seq); + + } + } catch (Exception e) + { + e.printStackTrace(); + } + } + + public SequenceFeature[] getJalviewSequenceFeatures( + JSONArray jsonSeqFeatures, Sequence seq) + { + SequenceFeature[] seqFeatures = null; + int count = 0; + if (jsonSeqFeatures != null) + { + seqFeatures = new SequenceFeature[jsonSeqFeatures.size()]; + for (@SuppressWarnings("unchecked") + Iterator seqFeatureItr = jsonSeqFeatures.iterator(); seqFeatureItr + .hasNext();) + { + + SequenceFeature sequenceFeature = new SequenceFeature(); + JSONObject jsonFeature = seqFeatureItr.next(); + Long begin = (Long) jsonFeature.get("xStart"); + Long end = (Long) jsonFeature.get("xEnd"); + String type = (String) jsonFeature.get("text"); + // String color = (String) jsonFeature.get("fillColor"); + + sequenceFeature.setBegin(seq.findPosition(begin.intValue())); + sequenceFeature.setEnd(seq.findPosition(end.intValue()) - 1); + sequenceFeature.setType(type); + seqFeatures[count++] = sequenceFeature; + } + } + return seqFeatures; + } + + public void LoadAlignmentFeatures(AlignFrame af) + { + + af.setShowSeqFeatures(true); + af.changeColour(cs); + af.setMenusForViewport(); + } + + private ColourSchemeI getJalviewColorScheme(String bioJsColourSchemeName) + { + ColourSchemeI jalviewColor = null; + for (JalviewBioJsColorSchemeMapper cs : JalviewBioJsColorSchemeMapper + .values()) + { + if (cs.getBioJsName().equals(bioJsColourSchemeName)) + { + jalviewColor = cs.getJvColourScheme(); + break; + } + } + return jalviewColor; + } + + @Override + public String print() + { + throw new UnsupportedOperationException( + "Print method of HtmlFile not yet supported!"); + } + +} diff --git a/src/jalview/io/HtmlSvgOutput.java b/src/jalview/io/HtmlSvgOutput.java index 68f9924..3c9c608 100644 --- a/src/jalview/io/HtmlSvgOutput.java +++ b/src/jalview/io/HtmlSvgOutput.java @@ -260,15 +260,40 @@ public class HtmlSvgOutput private String getHtml(String titleSvg, String alignmentSvg) { StringBuilder htmlSvg = new StringBuilder(); - htmlSvg.append("" - + "
    " - + "
    "); - htmlSvg.append(titleSvg); - htmlSvg.append("
    ").append(alignmentSvg); + htmlSvg.append("" + + ""); + htmlSvg.append("
    "); + htmlSvg.append( +"
    "); + htmlSvg.append( +"
    ") + .append(titleSvg) + .append("
    ") + .append("
    \n\n\n\n"); + htmlSvg.append( +"
    "); + htmlSvg.append( + "
    ") + .append(alignmentSvg) +.append("
    ") + .append("
    "); htmlSvg.append("
    "); + + htmlSvg.append("\n" + + "\n" + + ""); + return htmlSvg.toString(); } } diff --git a/src/jalview/io/IdentifyFile.java b/src/jalview/io/IdentifyFile.java index 9c7478b..4fb2516 100755 --- a/src/jalview/io/IdentifyFile.java +++ b/src/jalview/io/IdentifyFile.java @@ -136,8 +136,14 @@ public class IdentifyFile break; } + // if (data.matches("<(\"[^\"]*\"|'[^']*'|[^'\">])*>")) + if (data.matches("<(?i)html(\"[^\"]*\"|'[^']*'|[^'\">])*>")) + { + reply = "HTML"; + break; + } - if ((data.indexOf("<") > -1)) + if (data.matches("<(?i)rnaml (\"[^\"]*\"|'[^']*'|[^'\">])*>")) { reply = "RNAML"; @@ -275,6 +281,7 @@ public class IdentifyFile break; } + /* * // TODO comment out SimpleBLAST identification for Jalview 2.4.1 else * if (!lineswereskipped && data.indexOf("BLAST")<4) { reply = @@ -320,6 +327,7 @@ public class IdentifyFile public static void main(String[] args) { + for (int i = 0; args != null && i < args.length; i++) { IdentifyFile ider = new IdentifyFile(); diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java index 6fba9c6..1757239 100644 --- a/src/jalview/io/SequenceAnnotationReport.java +++ b/src/jalview/io/SequenceAnnotationReport.java @@ -22,6 +22,7 @@ package jalview.io; import java.util.ArrayList; import java.util.Hashtable; +import java.util.List; import java.util.Vector; import jalview.datamodel.DBRefEntry; @@ -54,30 +55,30 @@ public class SequenceAnnotationReport * TODO refactor to Jalview 'utilities' somehow. */ public void appendFeatures(final StringBuffer tooltipText2, int rpos, - SequenceFeature[] features) + List features) { appendFeatures(tooltipText2, rpos, features, null); } public void appendFeatures(final StringBuffer tooltipText2, int rpos, - SequenceFeature[] features, Hashtable minmax) + List features, Hashtable minmax) { String tmpString; if (features != null) { - for (int i = 0; i < features.length; i++) + for (SequenceFeature feature:features) { - if (features[i].getType().equals("disulfide bond")) + if (feature.getType().equals("disulfide bond")) { - if (features[i].getBegin() == rpos - || features[i].getEnd() == rpos) + if (feature.getBegin() == rpos + || feature.getEnd() == rpos) { if (tooltipText2.length() > 6) { tooltipText2.append("
    "); } - tooltipText2.append("disulfide bond " + features[i].getBegin() - + ":" + features[i].getEnd()); + tooltipText2.append("disulfide bond " + feature.getBegin() + + ":" + feature.getEnd()); } } else @@ -87,25 +88,25 @@ public class SequenceAnnotationReport tooltipText2.append("
    "); } // TODO: remove this hack to display link only features - boolean linkOnly = features[i].getValue("linkonly") != null; + boolean linkOnly = feature.getValue("linkonly") != null; if (!linkOnly) { - tooltipText2.append(features[i].getType() + " "); + tooltipText2.append(feature.getType() + " "); if (rpos != 0) { // we are marking a positional feature - tooltipText2.append(features[i].begin); + tooltipText2.append(feature.begin); } - if (features[i].begin != features[i].end) + if (feature.begin != feature.end) { - tooltipText2.append(" " + features[i].end); + tooltipText2.append(" " + feature.end); } - if (features[i].getDescription() != null - && !features[i].description.equals(features[i] + if (feature.getDescription() != null + && !feature.description.equals(feature .getType())) { - tmpString = features[i].getDescription(); + tmpString = feature.getDescription(); String tmp2up = tmpString.toUpperCase(); int startTag = tmp2up.indexOf(""); if (startTag > -1) @@ -150,27 +151,27 @@ public class SequenceAnnotationReport } } // check score should be shown - if (features[i].getScore() != Float.NaN) + if (feature.getScore() != Float.NaN) { float[][] rng = (minmax == null) ? null : ((float[][]) minmax - .get(features[i].getType())); + .get(feature.getType())); if (rng != null && rng[0] != null && rng[0][0] != rng[0][1]) { - tooltipText2.append(" Score=" + features[i].getScore()); + tooltipText2.append(" Score=" + feature.getScore()); } } - if (features[i].getValue("status") != null) + if (feature.getValue("status") != null) { - String status = features[i].getValue("status").toString(); + String status = feature.getValue("status").toString(); if (status.length() > 0) { - tooltipText2.append("; (" + features[i].getValue("status") + tooltipText2.append("; (" + feature.getValue("status") + ")"); } } } } - if (features[i].links != null) + if (feature.links != null) { if (linkImageURL != null) { @@ -178,7 +179,7 @@ public class SequenceAnnotationReport } else { - for (String urlstring : (Vector) features[i].links) + for (String urlstring : (Vector) feature.links) { try { @@ -364,7 +365,6 @@ public class SequenceAnnotationReport // ADD NON POSITIONAL SEQUENCE INFO SequenceFeature[] features = ds.getSequenceFeatures(); - SequenceFeature[] tfeat = new SequenceFeature[1]; if (showNpFeats && features != null) { for (int i = 0; i < features.length; i++) @@ -372,7 +372,8 @@ public class SequenceAnnotationReport if (features[i].begin == 0 && features[i].end == 0) { int sz = -tip.length(); - tfeat[0] = features[i]; + List tfeat = new ArrayList(); + tfeat.add(features[i]); appendFeatures(tip, 0, tfeat, minmax); sz += tip.length(); maxWidth = Math.max(maxWidth, sz); diff --git a/src/jalview/io/StockholmFile.java b/src/jalview/io/StockholmFile.java index 96c462c..3b9fb00 100644 --- a/src/jalview/io/StockholmFile.java +++ b/src/jalview/io/StockholmFile.java @@ -1027,13 +1027,21 @@ public class StockholmFile extends AlignFile } else { - label = (key = type2id(aa.label.toLowerCase())) + "_cons"; + key = type2id(aa.label.toLowerCase()); + if (key == null) + { + label = aa.label; + } + else + { + label = key + "_cons"; + } } - if (label == null) { label = aa.label; } + label = label.replace(" ", "_"); out.append(new Format("%-" + maxid + "s").form("#=GC " + label + " ")); @@ -1067,7 +1075,7 @@ public class StockholmFile extends AlignFile String ch = (annot == null) ? ((sequenceI == null) ? "-" : Character .toString(sequenceI.getCharAt(k))) : annot.displayCharacter; - if (key.equals("SS")) + if (key != null && key.equals("SS")) { if (annot == null) { diff --git a/src/jalview/javascript/MouseOverStructureListener.java b/src/jalview/javascript/MouseOverStructureListener.java index 465a672..2ecaf6c 100644 --- a/src/jalview/javascript/MouseOverStructureListener.java +++ b/src/jalview/javascript/MouseOverStructureListener.java @@ -202,7 +202,7 @@ public class MouseOverStructureListener extends JSFunctionExec implements SequenceRenderer sr = ((jalview.appletgui.AlignmentPanel) source) .getSequenceRenderer(); FeatureRenderer fr = ((jalview.appletgui.AlignmentPanel) source).av - .getShowSequenceFeatures() ? new jalview.appletgui.FeatureRenderer( + .isShowSequenceFeatures() ? new jalview.appletgui.FeatureRenderer( ((jalview.appletgui.AlignmentPanel) source).av) : null; if (fr != null) { diff --git a/src/jalview/jbgui/GAlignFrame.java b/src/jalview/jbgui/GAlignFrame.java index 387bb7f..4bf8176 100755 --- a/src/jalview/jbgui/GAlignFrame.java +++ b/src/jalview/jbgui/GAlignFrame.java @@ -214,6 +214,8 @@ public class GAlignFrame extends JInternalFrame JMenuItem createPNG = new JMenuItem(); + JMenuItem createBioJS = new JMenuItem(); + JMenuItem createSVG = new JMenuItem(); protected JMenuItem font = new JMenuItem(); @@ -1197,6 +1199,19 @@ public class GAlignFrame extends JInternalFrame htmlMenuItem_actionPerformed(e); } }); + + // TODO uncomment when supported by MassageManager + // createBioJS.setText(MessageManager.getString("label.biojs_html_export")); + createBioJS.setText("BioJS"); + createBioJS.addActionListener(new java.awt.event.ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + bioJSMenuItem_actionPerformed(e); + } + }); + overviewMenuItem.setText(MessageManager .getString("label.overview_window")); overviewMenuItem.addActionListener(new java.awt.event.ActionListener() @@ -1603,7 +1618,6 @@ public class GAlignFrame extends JInternalFrame font_actionPerformed(e); } }); - seqLimits.setText(MessageManager .getString("label.show_sequence_limits")); seqLimits.setState(jalview.bin.Cache.getDefault("SHOW_JVSUFFIX", true)); @@ -2353,6 +2367,7 @@ public class GAlignFrame extends JInternalFrame jMenu2.add(htmlMenuItem); jMenu2.add(epsFile); jMenu2.add(createPNG); + jMenu2.add(createBioJS); jMenu2.add(createSVG); addSequenceMenu.add(addFromFile); addSequenceMenu.add(addFromText); @@ -2611,6 +2626,11 @@ public class GAlignFrame extends JInternalFrame { } + protected void bioJSMenuItem_actionPerformed(ActionEvent e) + { + + } + protected void closeMenuItem_actionPerformed(boolean b) { } diff --git a/src/jalview/jbgui/GDesktop.java b/src/jalview/jbgui/GDesktop.java index 4751d25..97ec9fe 100755 --- a/src/jalview/jbgui/GDesktop.java +++ b/src/jalview/jbgui/GDesktop.java @@ -22,10 +22,16 @@ package jalview.jbgui; import jalview.util.MessageManager; -import java.awt.*; -import java.awt.event.*; +import java.awt.FlowLayout; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; -import javax.swing.*; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; /** * DOCUMENT ME! @@ -374,7 +380,7 @@ public class GDesktop extends JFrame toolsMenu.add(showConsole); toolsMenu.add(showNews); toolsMenu.add(garbageCollect); - toolsMenu.add(snapShotWindow); + // toolsMenu.add(snapShotWindow); inputMenu.add(inputLocalFileMenuItem); inputMenu.add(inputURLMenuItem); inputMenu.add(inputTextboxMenuItem); diff --git a/src/jalview/jbgui/GPreferences.java b/src/jalview/jbgui/GPreferences.java index 5569c24..610f32e 100755 --- a/src/jalview/jbgui/GPreferences.java +++ b/src/jalview/jbgui/GPreferences.java @@ -782,6 +782,15 @@ public class GPreferences extends JPanel structViewer.setBounds(new Rectangle(160, ypos, 120, height)); structViewer.addItem(Viewer.JMOL.name()); structViewer.addItem(Viewer.CHIMERA.name()); + structViewer.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + structureViewer_actionPerformed((String) structViewer + .getSelectedItem()); + } + }); structureTab.add(structViewer); ypos += lineSpacing; @@ -819,6 +828,15 @@ public class GPreferences extends JPanel } /** + * Action on choosing a structure viewer from combobox options. + * + * @param selectedItem + */ + protected void structureViewer_actionPerformed(String selectedItem) + { + } + + /** * Show a dialog for the user to choose a file. Returns the chosen path, or * null on Cancel. * diff --git a/src/jalview/json/binding/v1/BioJsAlignmentPojo.java b/src/jalview/json/binding/v1/BioJsAlignmentPojo.java new file mode 100644 index 0000000..8e8747f --- /dev/null +++ b/src/jalview/json/binding/v1/BioJsAlignmentPojo.java @@ -0,0 +1,151 @@ +package jalview.json.binding.v1; + +import jalview.schemes.Blosum62ColourScheme; +import jalview.schemes.BuriedColourScheme; +import jalview.schemes.ColourSchemeI; +import jalview.schemes.HelixColourScheme; +import jalview.schemes.HydrophobicColourScheme; +import jalview.schemes.NucleotideColourScheme; +import jalview.schemes.PIDColourScheme; +import jalview.schemes.PurinePyrimidineColourScheme; +import jalview.schemes.RNAInteractionColourScheme; +import jalview.schemes.StrandColourScheme; +import jalview.schemes.TaylorColourScheme; +import jalview.schemes.TurnColourScheme; +import jalview.schemes.ZappoColourScheme; + +import java.util.ArrayList; + +public class BioJsAlignmentPojo +{ + private String globalColorScheme = "none"; + + private String jalviewVersion; + + private String webStartUrl; + private ArrayList seqs = new ArrayList(); + + public BioJsAlignmentPojo() + { + + } + public ArrayList getSeqs() + { + return seqs; + } + + public void setSeqs(ArrayList seqs) + { + this.seqs = seqs; + } + public String getGlobalColorScheme() + { + return globalColorScheme; + } + public void setGlobalColorScheme(String globalColorScheme) + { + for (JalviewBioJsColorSchemeMapper cs : JalviewBioJsColorSchemeMapper + .values()) + { + if (cs.getJalviewName().equals(globalColorScheme)) + { + this.globalColorScheme = cs.getBioJsName(); + break; + } + } + + // JALVIEW colors not in biojs + // Blosum62 + // T-Coffee Scores (almost same with Blosom62 + // RNA Interaction type - no color applied + // RNA Helices - missing + + // BIOJS Colour not in jalview + // schemes.push name: "Lesk", id: "lesk" + // schemes.push name: "Cinema", id: "cinema" + // schemes.push name: "MAE", id: "mae" + // schemes.push name: "Clustal2", id: "clustal2" + + } + + + public String getJalviewVersion() + { + return jalviewVersion; + } + + public void setJalviewVersion(String jalviewVersion) + { + this.jalviewVersion = jalviewVersion; + } + + public String getWebStartUrl() + { + return webStartUrl; + } + + public void setWebStartUrl(String webStartUrl) + { + this.webStartUrl = webStartUrl; + } + + public enum JalviewBioJsColorSchemeMapper + { + USER_DEFINED("User Defined", "user defined", null), NONE("None", "foo", + null), CLUSTAL("Clustal", "clustal", null), ZAPPO("Zappo", + "zappo", new ZappoColourScheme()), TAYLOR( + "Taylor", "taylor", new TaylorColourScheme()), NUCLEOTIDE( + "Nucleotide", "nucleotide", new NucleotideColourScheme()), PURINE_PYRIMIDINE( + "Purine/Pyrimidine", "purine", + new PurinePyrimidineColourScheme()), HELIX_PROPENCITY( + "Helix Propensity", "helix", new HelixColourScheme()), TURN_PROPENSITY( + "Turn Propensity", "turn", new TurnColourScheme()), STRAND_PROPENSITY( + "Strand Propensity", "strand", new StrandColourScheme()), BURIED_INDEX( + "Buried Index", "buried", new BuriedColourScheme()), HYDROPHOBIC( + "Hydrophobic", "hydro", new HydrophobicColourScheme()), + + // The color types below are not yet supported by BioJs MSA viewer + T_COFFE_SCORES("T-Coffee Scores", "T-Coffee Scores", + null), RNA_INT_TYPE( + "RNA Interaction type", "RNA Interaction type", + new RNAInteractionColourScheme()), BLOSUM62("Blosum62", + "Blosum62", new Blosum62ColourScheme()), RNA_HELICES( + "RNA Helices", "RNA Helices", null), PERCENTAGE_IDENTITY( + "% Identity", "pid", + new PIDColourScheme()); + + private String jalviewName; + private String bioJsName; + + private ColourSchemeI jvColourScheme; + + private JalviewBioJsColorSchemeMapper(String jalviewName, + String bioJsName, ColourSchemeI jvColourScheme) + { + this.jalviewName = jalviewName; + this.bioJsName = bioJsName; + this.setJvColourScheme(jvColourScheme); + } + + public String getJalviewName() + { + return jalviewName; + } + + public String getBioJsName() + { + return bioJsName; + } + + public ColourSchemeI getJvColourScheme() + { + return jvColourScheme; + } + + public void setJvColourScheme(ColourSchemeI jvColourScheme) + { + this.jvColourScheme = jvColourScheme; + } + + } +} diff --git a/src/jalview/json/binding/v1/BioJsFeaturePojo.java b/src/jalview/json/binding/v1/BioJsFeaturePojo.java new file mode 100644 index 0000000..3c2fdda --- /dev/null +++ b/src/jalview/json/binding/v1/BioJsFeaturePojo.java @@ -0,0 +1,60 @@ +package jalview.json.binding.v1; + +public class BioJsFeaturePojo +{ + + private int xstart; + + private int xend; + + private String text; + + private String fillColor; + + public BioJsFeaturePojo() + { + } + + + public String getText() + { + return text; + } + + public void setText(String text) + { + this.text = text; + } + + public String getFillColor() + { + return "#" + fillColor; + } + + public void setFillColor(String fillColor) + { + this.fillColor = fillColor; + } + + public int getXstart() + { + return xstart; + } + + public void setXstart(int xstart) + { + this.xstart = xstart; + } + + public int getXend() + { + return xend; + } + + public void setXend(int xend) + { + this.xend = xend; + } + + +} diff --git a/src/jalview/json/binding/v1/BioJsSeqPojo.java b/src/jalview/json/binding/v1/BioJsSeqPojo.java new file mode 100644 index 0000000..bac8601 --- /dev/null +++ b/src/jalview/json/binding/v1/BioJsSeqPojo.java @@ -0,0 +1,90 @@ +package jalview.json.binding.v1; + +import java.util.ArrayList; + + +public class BioJsSeqPojo +{ + private String seq; + + private String name; + + private String id; + + private int start; + + private int end; + + private ArrayList features = new ArrayList(); + + public BioJsSeqPojo() + { + } + + public BioJsSeqPojo(int start, int end, String id, String name, String seq) + { + this.id = id; + this.name = name; + this.seq = seq; + } + public String getSeq() + { + return seq; + } + + public void setSeq(String seq) + { + this.seq = seq; + } + + public String getName() + { + + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public int getStart() + { + return start; + } + + public void setStart(int start) + { + this.start = start; + } + + public int getEnd() + { + return end; + } + + public void setEnd(int end) + { + this.end = end; + } + + public ArrayList getFeatures() + { + return features; + } + + public void setFeatures(ArrayList features) + { + this.features = features; + } +} diff --git a/src/jalview/renderer/seqfeatures/FeatureRenderer.java b/src/jalview/renderer/seqfeatures/FeatureRenderer.java new file mode 100644 index 0000000..5e6ac29 --- /dev/null +++ b/src/jalview/renderer/seqfeatures/FeatureRenderer.java @@ -0,0 +1,435 @@ +package jalview.renderer.seqfeatures; + +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; + +public class FeatureRenderer extends + jalview.viewmodel.seqfeatures.FeatureRendererModel +{ + + FontMetrics fm; + + int charOffset; + + boolean offscreenRender = false; + + /** + * DOCUMENT ME! + * + * @param g + * DOCUMENT ME! + * @param seq + * DOCUMENT ME! + * @param sg + * DOCUMENT ME! + * @param start + * DOCUMENT ME! + * @param end + * DOCUMENT ME! + * @param x1 + * DOCUMENT ME! + * @param y1 + * DOCUMENT ME! + * @param width + * DOCUMENT ME! + * @param height + * DOCUMENT ME! + */ + protected SequenceI lastSeq; + + char s; + + int i; + + int av_charHeight, av_charWidth; + + boolean av_validCharWidth, av_isShowSeqFeatureHeight; + + protected void updateAvConfig() + { + av_charHeight = av.getCharHeight(); + av_charWidth = av.getCharWidth(); + av_validCharWidth = av.isValidCharWidth(); + av_isShowSeqFeatureHeight = av.isShowSequenceFeaturesHeight(); + } + + void renderFeature(Graphics g, SequenceI seq, int fstart, int fend, + Color featureColour, int start, int end, int y1) + { + updateAvConfig(); + if (((fstart <= end) && (fend >= start))) + { + if (fstart < start) + { // fix for if the feature we have starts before the sequence start, + fstart = start; // but the feature end is still valid!! + } + + if (fend >= end) + { + fend = end; + } + int pady = (y1 + av_charHeight) - av_charHeight / 5; + for (i = fstart; i <= fend; i++) + { + s = seq.getCharAt(i); + + if (jalview.util.Comparison.isGap(s)) + { + continue; + } + + g.setColor(featureColour); + + g.fillRect((i - start) * av_charWidth, y1, av_charWidth, + av_charHeight); + + if (offscreenRender || !av_validCharWidth) + { + continue; + } + + g.setColor(Color.white); + charOffset = (av_charWidth - fm.charWidth(s)) / 2; + g.drawString(String.valueOf(s), charOffset + + (av_charWidth * (i - start)), pady); + + } + } + } + + void renderScoreFeature(Graphics g, SequenceI seq, int fstart, int fend, + Color featureColour, int start, int end, int y1, byte[] bs) + { + updateAvConfig(); + if (((fstart <= end) && (fend >= start))) + { + if (fstart < start) + { // fix for if the feature we have starts before the sequence start, + fstart = start; // but the feature end is still valid!! + } + + if (fend >= end) + { + fend = end; + } + int pady = (y1 + av_charHeight) - av_charHeight / 5; + int ystrt = 0, yend = av_charHeight; + if (bs[0] != 0) + { + // signed - zero is always middle of residue line. + if (bs[1] < 128) + { + yend = av_charHeight * (128 - bs[1]) / 512; + ystrt = av_charHeight - yend / 2; + } + else + { + ystrt = av_charHeight / 2; + yend = av_charHeight * (bs[1] - 128) / 512; + } + } + else + { + yend = av_charHeight * bs[1] / 255; + ystrt = av_charHeight - yend; + + } + for (i = fstart; i <= fend; i++) + { + s = seq.getCharAt(i); + + if (jalview.util.Comparison.isGap(s)) + { + continue; + } + + g.setColor(featureColour); + int x = (i - start) * av_charWidth; + g.drawRect(x, y1, av_charWidth, av_charHeight); + g.fillRect(x, y1 + ystrt, av_charWidth, yend); + + if (offscreenRender || !av_validCharWidth) + { + continue; + } + + g.setColor(Color.black); + charOffset = (av_charWidth - fm.charWidth(s)) / 2; + g.drawString(String.valueOf(s), charOffset + + (av_charWidth * (i - start)), pady); + + } + } + } + + BufferedImage offscreenImage; + + public Color findFeatureColour(Color initialCol, SequenceI seq, int res) + { + return new Color(findFeatureColour(initialCol.getRGB(), seq, res)); + } + + /** + * This is used by the Molecule Viewer and Overview to get the accurate + * colourof the rendered sequence + */ + public synchronized int findFeatureColour(int initialCol, final SequenceI seq, + int column) + { + if (!av.isShowSequenceFeatures()) + { + return initialCol; + } + + final SequenceI aseq = (seq.getDatasetSequence() != null) ? seq + .getDatasetSequence() : seq; + if (seq != lastSeq) + { + lastSeq = seq; + sequenceFeatures = aseq.getSequenceFeatures(); + if (sequenceFeatures != null) + { + sfSize = sequenceFeatures.length; + } + } + else + { + if (sequenceFeatures != aseq.getSequenceFeatures()) + { + sequenceFeatures = aseq.getSequenceFeatures(); + if (sequenceFeatures != null) + { + sfSize = sequenceFeatures.length; + } + } + } + + if (sequenceFeatures == null || sfSize == 0) + { + return initialCol; + } + + if (jalview.util.Comparison.isGap(lastSeq.getCharAt(column))) + { + return Color.white.getRGB(); + } + + // Only bother making an offscreen image if transparency is applied + if (transparency != 1.0f && offscreenImage == null) + { + offscreenImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); + } + + currentColour = null; + // TODO: non-threadsafe - each rendering thread needs its own instance of + // the feature renderer - or this should be synchronized. + offscreenRender = true; + + if (offscreenImage != null) + { + offscreenImage.setRGB(0, 0, initialCol); + drawSequence(offscreenImage.getGraphics(), lastSeq, column, column, 0); + + return offscreenImage.getRGB(0, 0); + } + else + { + drawSequence(null, lastSeq, lastSeq.findPosition(column), -1, -1); + + if (currentColour == null) + { + return initialCol; + } + else + { + return ((Integer) currentColour).intValue(); + } + } + + } + + private volatile SequenceFeature[] sequenceFeatures; + + int sfSize; + + int sfindex; + + int spos; + + int epos; + + public synchronized void drawSequence(Graphics g, final SequenceI seq, + int start, int end, int y1) + { + final SequenceI aseq = (seq.getDatasetSequence() != null) ? seq + .getDatasetSequence() : seq; + if (aseq.getSequenceFeatures() == null + || aseq.getSequenceFeatures().length == 0) + { + return; + } + + if (g != null) + { + fm = g.getFontMetrics(); + } + + updateFeatures(); + + if (lastSeq == null || seq != lastSeq + || aseq.getSequenceFeatures() != sequenceFeatures) + { + lastSeq = seq; + sequenceFeatures = aseq.getSequenceFeatures(); + } + + if (transparency != 1 && g != null) + { + Graphics2D g2 = (Graphics2D) g; + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, + transparency)); + } + + if (!offscreenRender) + { + spos = lastSeq.findPosition(start); + epos = lastSeq.findPosition(end); + } + + sfSize = sequenceFeatures.length; + String type; + for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++) + { + type = renderOrder[renderIndex]; + + if (type == null || !showFeatureOfType(type)) + { + continue; + } + + // loop through all features in sequence to find + // current feature to render + for (sfindex = 0; sfindex < sfSize; sfindex++) + { + if (!sequenceFeatures[sfindex].type.equals(type)) + { + continue; + } + + if (featureGroups != null + && sequenceFeatures[sfindex].featureGroup != null + && sequenceFeatures[sfindex].featureGroup.length() != 0 + && featureGroups + .containsKey(sequenceFeatures[sfindex].featureGroup) + && !featureGroups + .get(sequenceFeatures[sfindex].featureGroup) + .booleanValue()) + { + continue; + } + + if (!offscreenRender + && (sequenceFeatures[sfindex].getBegin() > epos || sequenceFeatures[sfindex] + .getEnd() < spos)) + { + continue; + } + + if (offscreenRender && offscreenImage == null) + { + if (sequenceFeatures[sfindex].begin <= start + && sequenceFeatures[sfindex].end >= start) + { + // this is passed out to the overview and other sequence renderers + // (e.g. molecule viewer) to get displayed colour for rendered + // sequence + currentColour = new Integer( + getColour(sequenceFeatures[sfindex]).getRGB()); + // used to be retreived from av.featuresDisplayed + // currentColour = av.featuresDisplayed + // .get(sequenceFeatures[sfindex].type); + + } + } + else if (sequenceFeatures[sfindex].type.equals("disulfide bond")) + { + + renderFeature(g, seq, + seq.findIndex(sequenceFeatures[sfindex].begin) - 1, + seq.findIndex(sequenceFeatures[sfindex].begin) - 1, + getColour(sequenceFeatures[sfindex]) + // new Color(((Integer) av.featuresDisplayed + // .get(sequenceFeatures[sfindex].type)).intValue()) + , start, end, y1); + renderFeature(g, seq, + seq.findIndex(sequenceFeatures[sfindex].end) - 1, + seq.findIndex(sequenceFeatures[sfindex].end) - 1, + getColour(sequenceFeatures[sfindex]) + // new Color(((Integer) av.featuresDisplayed + // .get(sequenceFeatures[sfindex].type)).intValue()) + , start, end, y1); + + } + else if (showFeature(sequenceFeatures[sfindex])) + { + if (av_isShowSeqFeatureHeight + && sequenceFeatures[sfindex].score != Float.NaN) + { + renderScoreFeature(g, seq, + seq.findIndex(sequenceFeatures[sfindex].begin) - 1, + seq.findIndex(sequenceFeatures[sfindex].end) - 1, + getColour(sequenceFeatures[sfindex]), start, end, y1, + normaliseScore(sequenceFeatures[sfindex])); + } + else + { + renderFeature(g, seq, + seq.findIndex(sequenceFeatures[sfindex].begin) - 1, + seq.findIndex(sequenceFeatures[sfindex].end) - 1, + getColour(sequenceFeatures[sfindex]), start, end, y1); + } + } + + } + + } + + if (transparency != 1.0f && g != null && transparencyAvailable) + { + Graphics2D g2 = (Graphics2D) g; + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, + 1.0f)); + } + } + + boolean transparencyAvailable = true; + + protected void setTransparencyAvailable(boolean isTransparencyAvailable) + { + transparencyAvailable = isTransparencyAvailable; + } + + @Override + public boolean isTransparencyAvailable() + { + return transparencyAvailable; + } + + /** + * Called when alignment in associated view has new/modified features to + * discover and display. + * + */ + public void featuresAdded() + { + lastSeq = null; + findAllFeatures(); + } +} diff --git a/src/jalview/schemes/AnnotationColourGradient.java b/src/jalview/schemes/AnnotationColourGradient.java index 3cada8b..85ec3aec0 100755 --- a/src/jalview/schemes/AnnotationColourGradient.java +++ b/src/jalview/schemes/AnnotationColourGradient.java @@ -258,7 +258,7 @@ public class AnnotationColourGradient extends FollowerColourScheme public Color findColour(char c, int j, SequenceI seq) { Color currentColour = Color.white; - AlignmentAnnotation annotation = (seqAssociated ? seqannot.get(seq) + AlignmentAnnotation annotation = (seqAssociated && seqannot!=null ? seqannot.get(seq) : this.annotation); if (annotation == null) { @@ -286,7 +286,8 @@ public class AnnotationColourGradient extends FollowerColourScheme || (annotationThreshold != null && (aboveAnnotationThreshold == ABOVE_THRESHOLD ? aj.value >= annotationThreshold.value : aj.value <= annotationThreshold.value))) { - if (predefinedColours && aj.colour != null) + if (predefinedColours && aj.colour != null + && !aj.colour.equals(Color.black)) { currentColour = aj.colour; } diff --git a/src/jalview/schemes/Blosum62ColourScheme.java b/src/jalview/schemes/Blosum62ColourScheme.java index 41f7781..70c7685 100755 --- a/src/jalview/schemes/Blosum62ColourScheme.java +++ b/src/jalview/schemes/Blosum62ColourScheme.java @@ -21,14 +21,13 @@ package jalview.schemes; import jalview.analysis.AAFrequency; - -import java.awt.Color; -import java.util.Map; - import jalview.datamodel.AnnotatedCollectionI; import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceI; +import java.awt.Color; +import java.util.Map; + public class Blosum62ColourScheme extends ResidueColourScheme { public Blosum62ColourScheme() @@ -59,6 +58,7 @@ public class Blosum62ColourScheme extends ResidueColourScheme if (max.indexOf(res) > -1) { + // TODO use a constant here? currentColour = new Color(154, 154, 255); } else @@ -74,6 +74,7 @@ public class Blosum62ColourScheme extends ResidueColourScheme if (c > 0) { + // TODO use a constant here? currentColour = new Color(204, 204, 255); } else diff --git a/src/jalview/schemes/ResidueProperties.java b/src/jalview/schemes/ResidueProperties.java index 8acf1f2..d13f0a9 100755 --- a/src/jalview/schemes/ResidueProperties.java +++ b/src/jalview/schemes/ResidueProperties.java @@ -20,6 +20,7 @@ */ package jalview.schemes; +import jalview.analysis.scoremodels.FeatureScoreModel; import jalview.analysis.scoremodels.PIDScoreModel; import jalview.api.analysis.ScoreModelI; @@ -1498,6 +1499,7 @@ public class ResidueProperties // scoreMatrices.put("Conservation EnhPos", new // ScoreMatrix("Conservation EnhPos",propMatrixEpos,0)); scoreMatrices.put("PID", new PIDScoreModel()); + scoreMatrices.put("Displayed Features", new FeatureScoreModel()); } private ResidueProperties() diff --git a/src/jalview/structure/StructureSelectionManager.java b/src/jalview/structure/StructureSelectionManager.java index 4359879..af00798 100644 --- a/src/jalview/structure/StructureSelectionManager.java +++ b/src/jalview/structure/StructureSelectionManager.java @@ -522,7 +522,6 @@ public class StructureSelectionManager { return; } - boolean removeMapping = true; String[] handlepdbs; Vector pdbs = new Vector(); for (int i = 0; i < pdbfiles.length; pdbs.addElement(pdbfiles[i++])) diff --git a/src/jalview/util/ColorUtils.java b/src/jalview/util/ColorUtils.java index fd76086..44ce010 100644 --- a/src/jalview/util/ColorUtils.java +++ b/src/jalview/util/ColorUtils.java @@ -60,6 +60,26 @@ public class ColorUtils } /** + * Convert to Tk colour code format + * + * @param colour + * @return + * @see http + * ://www.cgl.ucsf.edu/chimera/current/docs/UsersGuide/colortool.html# + * tkcode + */ + public static final String toTkCode(Color colour) + { + String colstring = "#" + ((colour.getRed() < 16) ? "0" : "") + + Integer.toHexString(colour.getRed()) + + ((colour.getGreen() < 16) ? "0" : "") + + Integer.toHexString(colour.getGreen()) + + ((colour.getBlue() < 16) ? "0" : "") + + Integer.toHexString(colour.getBlue()); + return colstring; + } + + /** * Returns a colour three shades darker. Note you can't guarantee that * brighterThan reverses this, as darkerThan may result in black. * diff --git a/src/jalview/viewmodel/AlignmentViewport.java b/src/jalview/viewmodel/AlignmentViewport.java index 1b42faf..a2da591 100644 --- a/src/jalview/viewmodel/AlignmentViewport.java +++ b/src/jalview/viewmodel/AlignmentViewport.java @@ -24,6 +24,7 @@ import jalview.analysis.Conservation; import jalview.api.AlignCalcManagerI; import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; +import jalview.api.FeaturesDisplayedI; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.AlignmentView; @@ -696,6 +697,7 @@ public abstract class AlignmentViewport implements AlignViewportI sequenceSetID = new String(newid); } + @Override public String getSequenceSetId() { if (sequenceSetID == null) @@ -1659,4 +1661,97 @@ public abstract class AlignmentViewport implements AlignViewportI { sequenceColours = null; }; + + FeaturesDisplayedI featuresDisplayed = null; + + @Override + public FeaturesDisplayedI getFeaturesDisplayed() + { + return featuresDisplayed; + } + + public void setFeaturesDisplayed(FeaturesDisplayedI featuresDisplayedI) + { + featuresDisplayed = featuresDisplayedI; + } + + public boolean areFeaturesDisplayed() + { + return featuresDisplayed != null && featuresDisplayed.getRegisterdFeaturesCount()>0; + } + + /** + * display setting for showing/hiding sequence features on alignment view + */ + boolean showSequenceFeatures = false; + + /** + * set the flag + * + * @param b + * features are displayed if true + */ + @Override + public void setShowSequenceFeatures(boolean b) + { + showSequenceFeatures = b; + } + @Override + public boolean isShowSequenceFeatures() + { + return showSequenceFeatures; + } + + boolean showSeqFeaturesHeight; + + public void setShowSequenceFeaturesHeight(boolean selected) + { + showSeqFeaturesHeight = selected; + } + + public boolean isShowSequenceFeaturesHeight() + { + return showSeqFeaturesHeight; + } + + private boolean showAnnotation = true; + + private boolean rightAlignIds = false; + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean getShowAnnotation() + { + return isShowAnnotation(); + } + + /** + * DOCUMENT ME! + * + * @param b + * DOCUMENT ME! + */ + public void setShowAnnotation(boolean b) + { + showAnnotation = b; + } + + public boolean isShowAnnotation() + { + return showAnnotation; + } + + public boolean isRightAlignIds() + { + return rightAlignIds; + } + + public void setRightAlignIds(boolean rightAlignIds) + { + this.rightAlignIds = rightAlignIds; + } + } diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java new file mode 100644 index 0000000..c7cee04 --- /dev/null +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@ -0,0 +1,949 @@ +package jalview.viewmodel.seqfeatures; + +import jalview.api.AlignViewportI; +import jalview.api.FeaturesDisplayedI; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.renderer.seqfeatures.FeatureRenderer; +import jalview.schemes.GraduatedColor; +import jalview.viewmodel.AlignmentViewport; + +import java.awt.Color; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class FeatureRendererModel implements + jalview.api.FeatureRenderer +{ + + /** + * global transparency for feature + */ + protected float transparency = 1.0f; + + protected Map featureColours = new ConcurrentHashMap(); + + protected Map featureGroups = new ConcurrentHashMap(); + + protected Object currentColour; + + protected String[] renderOrder; + + protected PropertyChangeSupport changeSupport = new PropertyChangeSupport( + this); + + protected AlignmentViewport av; + + public AlignViewportI getViewport() + { + return av; + } + + public FeatureRendererSettings getSettings() + { + return new FeatureRendererSettings(this); + } + + public void transferSettings(FeatureRendererSettings fr) + { + this.renderOrder = fr.renderOrder; + this.featureGroups = fr.featureGroups; + this.featureColours = fr.featureColours; + this.transparency = fr.transparency; + this.featureOrder = fr.featureOrder; + } + + /** + * update from another feature renderer + * + * @param fr + * settings to copy + */ + public void transferSettings(jalview.api.FeatureRenderer _fr) + { + FeatureRenderer fr = (FeatureRenderer) _fr; + FeatureRendererSettings frs = new FeatureRendererSettings(fr); + this.renderOrder = frs.renderOrder; + this.featureGroups = frs.featureGroups; + this.featureColours = frs.featureColours; + this.transparency = frs.transparency; + this.featureOrder = frs.featureOrder; + if (av != null && av != fr.getViewport()) + { + // copy over the displayed feature settings + if (_fr.getFeaturesDisplayed() != null) + { + FeaturesDisplayedI fd = getFeaturesDisplayed(); + if (fd == null) + { + setFeaturesDisplayedFrom(_fr.getFeaturesDisplayed()); + } + else + { + synchronized (fd) + { + fd.clear(); + java.util.Iterator fdisp = _fr.getFeaturesDisplayed() + .getVisibleFeatures(); + while (fdisp.hasNext()) + { + fd.setVisible(fdisp.next()); + } + } + } + } + } + } + + public void setFeaturesDisplayedFrom(FeaturesDisplayedI featuresDisplayed) + { + av.setFeaturesDisplayed(new FeaturesDisplayed(featuresDisplayed)); + } + + @Override + public void setVisible(String featureType) + { + FeaturesDisplayedI fdi = av.getFeaturesDisplayed(); + if (fdi == null) + { + av.setFeaturesDisplayed(fdi = new FeaturesDisplayed()); + } + if (!fdi.isRegistered(featureType)) + { + pushFeatureType(Arrays.asList(new String[] + { featureType })); + } + fdi.setVisible(featureType); + } + + @Override + public void setAllVisible(List featureTypes) + { + FeaturesDisplayedI fdi = av.getFeaturesDisplayed(); + if (fdi == null) + { + av.setFeaturesDisplayed(fdi = new FeaturesDisplayed()); + } + List nft = new ArrayList(); + for (String featureType : featureTypes) + { + if (!fdi.isRegistered(featureType)) + { + nft.add(featureType); + } + } + if (nft.size() > 0) + { + pushFeatureType(nft); + } + fdi.setAllVisible(featureTypes); + } + + /** + * push a set of new types onto the render order stack. Note - this is a + * direct mechanism rather than the one employed in updateRenderOrder + * + * @param types + */ + private void pushFeatureType(List types) + { + + int ts = types.size(); + String neworder[] = new String[(renderOrder == null ? 0 + : renderOrder.length) + ts]; + types.toArray(neworder); + if (renderOrder != null) + { + System.arraycopy(neworder,0,neworder,renderOrder.length,ts); + System.arraycopy(renderOrder, 0, neworder, 0, renderOrder.length); + } + renderOrder = neworder; + } + + protected Hashtable minmax = new Hashtable(); + + public Hashtable getMinMax() + { + return minmax; + } + + /** + * normalise a score against the max/min bounds for the feature type. + * + * @param sequenceFeature + * @return byte[] { signed, normalised signed (-127 to 127) or unsigned + * (0-255) value. + */ + protected final byte[] normaliseScore(SequenceFeature sequenceFeature) + { + float[] mm = ((float[][]) minmax.get(sequenceFeature.type))[0]; + final byte[] r = new byte[] + { 0, (byte) 255 }; + if (mm != null) + { + if (r[0] != 0 || mm[0] < 0.0) + { + r[0] = 1; + r[1] = (byte) ((int) 128.0 + 127.0 * (sequenceFeature.score / mm[1])); + } + else + { + r[1] = (byte) ((int) 255.0 * (sequenceFeature.score / mm[1])); + } + } + return r; + } + + boolean newFeatureAdded = false; + + boolean findingFeatures = false; + + protected boolean updateFeatures() + { + if (av.getFeaturesDisplayed() == null || renderOrder == null + || newFeatureAdded) + { + findAllFeatures(); + if (av.getFeaturesDisplayed().getVisibleFeatureCount() < 1) + { + return false; + } + } + // TODO: decide if we should check for the visible feature count first + return true; + } + + /** + * search the alignment for all new features, give them a colour and display + * them. Then fires a PropertyChangeEvent on the changeSupport object. + * + */ + protected void findAllFeatures() + { + synchronized (firing) + { + if (firing.equals(Boolean.FALSE)) + { + firing = Boolean.TRUE; + findAllFeatures(true); // add all new features as visible + changeSupport.firePropertyChange("changeSupport", null, null); + firing = Boolean.FALSE; + } + } + } + + @Override + public List findFeaturesAtRes(SequenceI sequence, int res) + { + ArrayList tmp = new ArrayList(); + SequenceFeature[] features = sequence.getSequenceFeatures(); + + while (features == null && sequence.getDatasetSequence() != null) + { + sequence = sequence.getDatasetSequence(); + features = sequence.getSequenceFeatures(); + } + + if (features != null) + { + for (int i = 0; i < features.length; i++) + { + if (!av.areFeaturesDisplayed() + || !av.getFeaturesDisplayed().isVisible( + features[i].getType())) + { + continue; + } + + if (features[i].featureGroup != null + && featureGroups != null + && featureGroups.containsKey(features[i].featureGroup) + && !featureGroups.get(features[i].featureGroup) + .booleanValue()) + { + continue; + } + + if ((features[i].getBegin() <= res) + && (features[i].getEnd() >= res)) + { + tmp.add(features[i]); + } + } + } + return tmp; + } + + /** + * Searches alignment for all features and updates colours + * + * @param newMadeVisible + * if true newly added feature types will be rendered immediatly + * TODO: check to see if this method should actually be proxied so + * repaint events can be propagated by the renderer code + */ + @Override + public synchronized void findAllFeatures(boolean newMadeVisible) + { + newFeatureAdded = false; + + if (findingFeatures) + { + newFeatureAdded = true; + return; + } + + findingFeatures = true; + if (av.getFeaturesDisplayed() == null) + { + av.setFeaturesDisplayed(new FeaturesDisplayed()); + } + FeaturesDisplayedI featuresDisplayed = av.getFeaturesDisplayed(); + + ArrayList allfeatures = new ArrayList(); + ArrayList oldfeatures = new ArrayList(); + if (renderOrder != null) + { + for (int i = 0; i < renderOrder.length; i++) + { + if (renderOrder[i] != null) + { + oldfeatures.add(renderOrder[i]); + } + } + } + if (minmax == null) + { + minmax = new Hashtable(); + } + AlignmentI alignment = av.getAlignment(); + for (int i = 0; i < alignment.getHeight(); i++) + { + SequenceI asq = alignment.getSequenceAt(i); + SequenceI dasq = asq.getDatasetSequence(); + SequenceFeature[] features = dasq != null ? dasq + .getSequenceFeatures() : asq.getSequenceFeatures(); + + if (features == null) + { + continue; + } + + int index = 0; + while (index < features.length) + { + if (!featuresDisplayed.isRegistered(features[index].getType())) + { + String fgrp = features[index].getFeatureGroup(); + if (fgrp != null) + { + Boolean groupDisplayed = featureGroups.get(fgrp); + if (groupDisplayed == null) + { + groupDisplayed = Boolean.valueOf(newMadeVisible); + featureGroups.put(fgrp, groupDisplayed); + } + if (!groupDisplayed.booleanValue()) + { + index++; + continue; + } + } + if (!(features[index].begin == 0 && features[index].end == 0)) + { + // If beginning and end are 0, the feature is for the whole sequence + // and we don't want to render the feature in the normal way + + if (newMadeVisible + && !oldfeatures.contains(features[index].getType())) + { + // this is a new feature type on the alignment. Mark it for + // display. + featuresDisplayed.setVisible(features[index].getType()); + setOrder(features[index].getType(), 0); + } + } + } + if (!allfeatures.contains(features[index].getType())) + { + allfeatures.add(features[index].getType()); + } + if (features[index].score != Float.NaN) + { + int nonpos = features[index].getBegin() >= 1 ? 0 : 1; + float[][] mm = (float[][]) minmax.get(features[index].getType()); + if (mm == null) + { + mm = new float[][] + { null, null }; + minmax.put(features[index].getType(), mm); + } + if (mm[nonpos] == null) + { + mm[nonpos] = new float[] + { features[index].score, features[index].score }; + + } + else + { + if (mm[nonpos][0] > features[index].score) + { + mm[nonpos][0] = features[index].score; + } + if (mm[nonpos][1] < features[index].score) + { + mm[nonpos][1] = features[index].score; + } + } + } + index++; + } + } + updateRenderOrder(allfeatures); + findingFeatures = false; + } + + protected Boolean firing = Boolean.FALSE; + + /** + * replaces the current renderOrder with the unordered features in + * allfeatures. The ordering of any types in both renderOrder and allfeatures + * is preserved, and all new feature types are rendered on top of the existing + * types, in the order given by getOrder or the order given in allFeatures. + * Note. this operates directly on the featureOrder hash for efficiency. TODO: + * eliminate the float storage for computing/recalling the persistent ordering + * New Cability: updates min/max for colourscheme range if its dynamic + * + * @param allFeatures + */ + private void updateRenderOrder(List allFeatures) + { + List allfeatures = new ArrayList(allFeatures); + String[] oldRender = renderOrder; + renderOrder = new String[allfeatures.size()]; + Object mmrange, fc = null; + boolean initOrders = (featureOrder == null); + int opos = 0; + if (oldRender != null && oldRender.length > 0) + { + for (int j = 0; j < oldRender.length; j++) + { + if (oldRender[j] != null) + { + if (initOrders) + { + setOrder(oldRender[j], (1 - (1 + (float) j) + / oldRender.length)); + } + if (allfeatures.contains(oldRender[j])) + { + renderOrder[opos++] = oldRender[j]; // existing features always + // appear below new features + allfeatures.remove(oldRender[j]); + if (minmax != null) + { + mmrange = minmax.get(oldRender[j]); + if (mmrange != null) + { + fc = featureColours.get(oldRender[j]); + if (fc != null && fc instanceof GraduatedColor + && ((GraduatedColor) fc).isAutoScale()) + { + ((GraduatedColor) fc).updateBounds( + ((float[][]) mmrange)[0][0], + ((float[][]) mmrange)[0][1]); + } + } + } + } + } + } + } + if (allfeatures.size() == 0) + { + // no new features - leave order unchanged. + return; + } + int i = allfeatures.size() - 1; + int iSize = i; + boolean sort = false; + String[] newf = new String[allfeatures.size()]; + float[] sortOrder = new float[allfeatures.size()]; + for (String newfeat : allfeatures) + { + newf[i] = newfeat; + if (minmax != null) + { + // update from new features minmax if necessary + mmrange = minmax.get(newf[i]); + if (mmrange != null) + { + fc = featureColours.get(newf[i]); + if (fc != null && fc instanceof GraduatedColor + && ((GraduatedColor) fc).isAutoScale()) + { + ((GraduatedColor) fc).updateBounds(((float[][]) mmrange)[0][0], + ((float[][]) mmrange)[0][1]); + } + } + } + if (initOrders || !featureOrder.containsKey(newf[i])) + { + int denom = initOrders ? allfeatures.size() : featureOrder.size(); + // new unordered feature - compute persistent ordering at head of + // existing features. + setOrder(newf[i], i / (float) denom); + } + // set order from newly found feature from persisted ordering. + sortOrder[i] = 2 - ((Float) featureOrder.get(newf[i])).floatValue(); + if (i < iSize) + { + // only sort if we need to + sort = sort || sortOrder[i] > sortOrder[i + 1]; + } + i--; + } + if (iSize > 1 && sort) + { + jalview.util.QuickSort.sort(sortOrder, newf); + } + sortOrder = null; + System.arraycopy(newf, 0, renderOrder, opos, newf.length); + } + + /** + * get a feature style object for the given type string. Creates a + * java.awt.Color for a featureType with no existing colourscheme. TODO: + * replace return type with object implementing standard abstract colour/style + * interface + * + * @param featureType + * @return java.awt.Color or GraduatedColor + */ + public Object getFeatureStyle(String featureType) + { + Object fc = featureColours.get(featureType); + if (fc == null) + { + jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme(); + Color col = ucs.createColourFromName(featureType); + featureColours.put(featureType, fc = col); + } + return fc; + } + + /** + * return a nominal colour for this feature + * + * @param featureType + * @return standard color, or maximum colour for graduated colourscheme + */ + public Color getColour(String featureType) + { + Object fc = getFeatureStyle(featureType); + + if (fc instanceof Color) + { + return (Color) fc; + } + else + { + if (fc instanceof GraduatedColor) + { + return ((GraduatedColor) fc).getMaxColor(); + } + } + throw new Error("Implementation Error: Unrecognised render object " + + fc.getClass() + " for features of type " + featureType); + } + + /** + * calculate the render colour for a specific feature using current feature + * settings. + * + * @param feature + * @return render colour for the given feature + */ + public Color getColour(SequenceFeature feature) + { + Object fc = getFeatureStyle(feature.getType()); + if (fc instanceof Color) + { + return (Color) fc; + } + else + { + if (fc instanceof GraduatedColor) + { + return ((GraduatedColor) fc).findColor(feature); + } + } + throw new Error("Implementation Error: Unrecognised render object " + + fc.getClass() + " for features of type " + feature.getType()); + } + + protected boolean showFeature(SequenceFeature sequenceFeature) + { + Object fc = getFeatureStyle(sequenceFeature.type); + if (fc instanceof GraduatedColor) + { + return ((GraduatedColor) fc).isColored(sequenceFeature); + } + else + { + return true; + } + } + + protected boolean showFeatureOfType(String type) + { + return av.getFeaturesDisplayed().isVisible(type); + } + + public void setColour(String featureType, Object col) + { + // overwrite + // Color _col = (col instanceof Color) ? ((Color) col) : (col instanceof + // GraduatedColor) ? ((GraduatedColor) col).getMaxColor() : null; + // Object c = featureColours.get(featureType); + // if (c == null || c instanceof Color || (c instanceof GraduatedColor && + // !((GraduatedColor)c).getMaxColor().equals(_col))) + { + featureColours.put(featureType, col); + } + } + + public void setTransparency(float value) + { + transparency = value; + } + + public float getTransparency() + { + return transparency; + } + + Map featureOrder = null; + + /** + * analogous to colour - store a normalized ordering for all feature types in + * this rendering context. + * + * @param type + * Feature type string + * @param position + * normalized priority - 0 means always appears on top, 1 means + * always last. + */ + public float setOrder(String type, float position) + { + if (featureOrder == null) + { + featureOrder = new Hashtable(); + } + featureOrder.put(type, new Float(position)); + return position; + } + + /** + * get the global priority (0 (top) to 1 (bottom)) + * + * @param type + * @return [0,1] or -1 for a type without a priority + */ + public float getOrder(String type) + { + if (featureOrder != null) + { + if (featureOrder.containsKey(type)) + { + return ((Float) featureOrder.get(type)).floatValue(); + } + } + return -1; + } + + @Override + public Map getFeatureColours() + { + return new ConcurrentHashMap(featureColours); + } + + /** + * Replace current ordering with new ordering + * + * @param data + * { String(Type), Colour(Type), Boolean(Displayed) } + */ + public void setFeaturePriority(Object[][] data) + { + setFeaturePriority(data, true); + } + + /** + * + * @param data + * { String(Type), Colour(Type), Boolean(Displayed) } + * @param visibleNew + * when true current featureDisplay list will be cleared + */ + public void setFeaturePriority(Object[][] data, boolean visibleNew) + { + FeaturesDisplayedI av_featuresdisplayed = null; + if (visibleNew) + { + if ((av_featuresdisplayed = av.getFeaturesDisplayed()) != null) + { + av.getFeaturesDisplayed().clear(); + } + else + { + av.setFeaturesDisplayed(av_featuresdisplayed = new FeaturesDisplayed()); + } + } + else + { + av_featuresdisplayed = av.getFeaturesDisplayed(); + } + if (data == null) + { + return; + } + // The feature table will display high priority + // features at the top, but theses are the ones + // we need to render last, so invert the data + renderOrder = new String[data.length]; + + if (data.length > 0) + { + for (int i = 0; i < data.length; i++) + { + String type = data[i][0].toString(); + setColour(type, data[i][1]); // todo : typesafety - feature color + // interface object + if (((Boolean) data[i][2]).booleanValue()) + { + av_featuresdisplayed.setVisible(type); + } + + renderOrder[data.length - i - 1] = type; + } + } + + } + + /** + * @param listener + * @see java.beans.PropertyChangeSupport#addPropertyChangeListener(java.beans.PropertyChangeListener) + */ + public void addPropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.addPropertyChangeListener(listener); + } + + /** + * @param listener + * @see java.beans.PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener) + */ + public void removePropertyChangeListener(PropertyChangeListener listener) + { + changeSupport.removePropertyChangeListener(listener); + } + + public Set getAllFeatureColours() + { + return featureColours.keySet(); + } + + public void clearRenderOrder() + { + renderOrder = null; + } + + public boolean hasRenderOrder() + { + return renderOrder != null; + } + + public List getRenderOrder() + { + if (renderOrder == null) + { + return Arrays.asList(new String[] + {}); + } + return Arrays.asList(renderOrder); + } + + public int getFeatureGroupsSize() + { + return featureGroups != null ? 0 : featureGroups.size(); + } + + @Override + public List getFeatureGroups() + { + // conflict between applet and desktop - featureGroups returns the map in + // the desktop featureRenderer + return (featureGroups == null) ? Arrays.asList(new String[0]) : Arrays + .asList(featureGroups.keySet().toArray(new String[0])); + } + + public boolean checkGroupVisibility(String group, boolean newGroupsVisible) + { + if (featureGroups == null) + { + // then an exception happens next.. + } + if (featureGroups.containsKey(group)) + { + return featureGroups.get(group).booleanValue(); + } + if (newGroupsVisible) + { + featureGroups.put(group, new Boolean(true)); + return true; + } + return false; + } + + /** + * get visible or invisible groups + * + * @param visible + * true to return visible groups, false to return hidden ones. + * @return list of groups + */ + @Override + public List getGroups(boolean visible) + { + if (featureGroups != null) + { + ArrayList gp = new ArrayList(); + + for (Object grp : featureGroups.keySet()) + { + Boolean state = featureGroups.get(grp); + if (state.booleanValue() == visible) + { + gp.add(grp); + } + } + return gp; + } + return null; + } + + @Override + public void setGroupVisibility(String group, boolean visible) + { + featureGroups.put(group, new Boolean(visible)); + } + + @Override + public void setGroupVisibility(List toset, boolean visible) + { + if (toset != null && toset.size() > 0 && featureGroups != null) + { + boolean rdrw = false; + for (String gst : toset) + { + Boolean st = featureGroups.get(gst); + featureGroups.put(gst, new Boolean(visible)); + if (st != null) + { + rdrw = rdrw || (visible != st.booleanValue()); + } + } + if (rdrw) + { + // set local flag indicating redraw needed ? + } + } + } + + @Override + public Hashtable getDisplayedFeatureCols() + { + Hashtable fcols = new Hashtable(); + if (getViewport().getFeaturesDisplayed() == null) + { + return fcols; + } + Iterator en = getViewport().getFeaturesDisplayed() + .getVisibleFeatures(); + while (en.hasNext()) + { + String col = en.next(); + fcols.put(col, getColour(col)); + } + return fcols; + } + + @Override + public FeaturesDisplayedI getFeaturesDisplayed() + { + return av.getFeaturesDisplayed(); + } + + @Override + public String[] getDisplayedFeatureTypes() + { + String[] typ = null; + typ = getRenderOrder().toArray(new String[0]); + FeaturesDisplayedI feature_disp = av.getFeaturesDisplayed(); + if (feature_disp != null) + { + synchronized (feature_disp) + { + for (int i = 0; i < typ.length; i++) + { + if (!feature_disp.isVisible(typ[i])) + { + typ[i] = null; + } + } + } + } + return typ; + } + + @Override + public String[] getDisplayedFeatureGroups() + { + String[] gps = null; + ArrayList _gps = new ArrayList(); + Iterator en = getFeatureGroups().iterator(); + int g = 0; + boolean valid = false; + while (en.hasNext()) + { + String gp = (String) en.next(); + if (checkGroupVisibility(gp, false)) + { + valid = true; + _gps.add(gp); + } + if (!valid) + { + return null; + } + else + { + gps = new String[_gps.size()]; + _gps.toArray(gps); + } + } + return gps; + } + +} diff --git a/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java b/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java new file mode 100644 index 0000000..6e85b83 --- /dev/null +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererSettings.java @@ -0,0 +1,77 @@ +package jalview.viewmodel.seqfeatures; + +import jalview.schemes.GraduatedColor; + +import java.util.Arrays; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class FeatureRendererSettings implements Cloneable +{ + String[] renderOrder; + + Map featureGroups; + + Map featureColours; + + float transparency; + + Map featureOrder; + + public FeatureRendererSettings(String[] renderOrder, + Hashtable featureGroups, Hashtable featureColours, + float transparency, Hashtable featureOrder) + { + super(); + this.renderOrder = Arrays.copyOf(renderOrder,renderOrder.length); + this.featureGroups = new ConcurrentHashMap(featureGroups); + this.featureColours = new ConcurrentHashMap(featureColours); + this.transparency = transparency; + this.featureOrder = new ConcurrentHashMap(featureOrder); + } + + /** + * create an independent instance of the feature renderer settings + * + * @param fr + */ + public FeatureRendererSettings( + jalview.viewmodel.seqfeatures.FeatureRendererModel fr) + { + renderOrder = null; + featureGroups = new ConcurrentHashMap(); + featureColours = new ConcurrentHashMap(); + featureOrder = new ConcurrentHashMap(); + if (fr.renderOrder != null) + { + this.renderOrder = new String[fr.renderOrder.length]; + System.arraycopy(fr.renderOrder, 0, renderOrder, 0, + fr.renderOrder.length); + } + if (fr.featureGroups != null) + { + this.featureGroups = new ConcurrentHashMap(fr.featureGroups); + } + if (fr.featureColours != null) + { + this.featureColours = new ConcurrentHashMap(fr.featureColours); + } + Iterator en = fr.featureColours.keySet().iterator(); + while (en.hasNext()) + { + Object next = en.next(); + Object val = featureColours.get(next); + if (val instanceof GraduatedColor) + { + featureColours.put(next, new GraduatedColor((GraduatedColor) val)); + } + } + this.transparency = fr.transparency; + if (fr.featureOrder != null) + { + this.featureOrder = new ConcurrentHashMap(fr.featureOrder); + } + } +} \ No newline at end of file diff --git a/src/jalview/viewmodel/seqfeatures/FeatureSettingsModel.java b/src/jalview/viewmodel/seqfeatures/FeatureSettingsModel.java new file mode 100644 index 0000000..57d57da --- /dev/null +++ b/src/jalview/viewmodel/seqfeatures/FeatureSettingsModel.java @@ -0,0 +1,8 @@ +package jalview.viewmodel.seqfeatures; + +import jalview.api.FeatureSettingsModelI; + +public class FeatureSettingsModel implements FeatureSettingsModelI +{ + +} diff --git a/src/jalview/viewmodel/seqfeatures/FeaturesDisplayed.java b/src/jalview/viewmodel/seqfeatures/FeaturesDisplayed.java new file mode 100644 index 0000000..b04764c --- /dev/null +++ b/src/jalview/viewmodel/seqfeatures/FeaturesDisplayed.java @@ -0,0 +1,94 @@ +package jalview.viewmodel.seqfeatures; + +import jalview.api.FeaturesDisplayedI; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; + +public class FeaturesDisplayed implements FeaturesDisplayedI +{ + private HashSet featuresDisplayed = new HashSet(); + + private HashSet featuresRegistered = new HashSet(); + + public FeaturesDisplayed(FeaturesDisplayedI featuresDisplayed2) + { + Iterator fdisp = featuresDisplayed2.getVisibleFeatures(); + String ftype; + while (fdisp.hasNext()) + { + ftype = fdisp.next(); + featuresDisplayed.add(ftype); + featuresRegistered.add(ftype); + } + } + + public FeaturesDisplayed() + { + // TODO Auto-generated constructor stub + } + + @Override + public Iterator getVisibleFeatures() + { + return featuresDisplayed.iterator(); + } + + @Override + public boolean isVisible(String featureType) + { + return featuresDisplayed.contains(featureType); + } + + @Override + public boolean areVisible(Collection featureTypes) + { + return featuresDisplayed.containsAll(featureTypes); + } + + @Override + public void clear() + { + featuresDisplayed.clear(); + featuresRegistered.clear(); + } + + @Override + public void setAllVisible(Collection makeVisible) + { + featuresDisplayed.addAll(makeVisible); + featuresRegistered.addAll(makeVisible); + } + + @Override + public void setAllRegisteredVisible() + { + featuresDisplayed.addAll(featuresRegistered); + } + + @Override + public void setVisible(String featureType) + { + featuresDisplayed.add(featureType); + featuresRegistered.add(featureType); + } + + @Override + public boolean isRegistered(String type) + { + return featuresRegistered.contains(type); + } + + @Override + public int getVisibleFeatureCount() + { + return featuresDisplayed.size(); + } + + @Override + public int getRegisterdFeaturesCount() + { + return featuresRegistered.size(); + } +} diff --git a/src/jalview/ws/AWSThread.java b/src/jalview/ws/AWSThread.java index edb56a9..d3682d4 100644 --- a/src/jalview/ws/AWSThread.java +++ b/src/jalview/ws/AWSThread.java @@ -28,7 +28,7 @@ import jalview.datamodel.AlignmentView; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; import jalview.gui.WebserviceInfo; -import jalview.gui.FeatureRenderer.FeatureRendererSettings; +import jalview.viewmodel.seqfeatures.FeatureRendererSettings; import jalview.util.MessageManager; public abstract class AWSThread extends Thread diff --git a/src/jalview/ws/DasSequenceFeatureFetcher.java b/src/jalview/ws/DasSequenceFeatureFetcher.java index 8a7bcbc..a778ab1 100644 --- a/src/jalview/ws/DasSequenceFeatureFetcher.java +++ b/src/jalview/ws/DasSequenceFeatureFetcher.java @@ -496,13 +496,13 @@ public class DasSequenceFeatureFetcher } catch (Exception ex) { Cache.log - .info("Error in 'experimental' mapping of features. Please try to reproduce and then report info to jalview-discuss@jalview.org."); - Cache.log.info("Mapping feature from " + f.getBegin() + .warn("Error in 'experimental' mapping of features. Please try to reproduce and then report info to jalview-discuss@jalview.org."); + Cache.log.warn("Mapping feature from " + f.getBegin() + " to " + f.getEnd() + " in dbref " + dbref.getAccessionId() + " in " + dbref.getSource()); - Cache.log.info("using das Source " + source); - Cache.log.info("Exception", ex); + Cache.log.warn("using das Source " + source); + Cache.log.warn("Exception", ex); } if (vf != null) @@ -626,7 +626,9 @@ public class DasSequenceFeatureFetcher Object[] nextSequence(jalviewSourceI dasSource, SequenceI seq) { if (cancelled) + { return null; + } DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs( seq.getDBRef(), new String[] { @@ -668,7 +670,9 @@ public class DasSequenceFeatureFetcher qstring.add(uprefs[j].getAccessionId()); } else + { System.out.println("IGNORE " + csys.getAuthority()); + } } } } @@ -839,7 +843,7 @@ public class DasSequenceFeatureFetcher { for (String note : feat.getNOTE()) { - desc += (String) note; + desc += note; } } diff --git a/src/jalview/ws/HttpClientUtils.java b/src/jalview/ws/HttpClientUtils.java index 229fa4e..1bdf64f 100644 --- a/src/jalview/ws/HttpClientUtils.java +++ b/src/jalview/ws/HttpClientUtils.java @@ -29,6 +29,7 @@ import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; +import org.apache.http.HttpVersion; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; @@ -40,6 +41,9 @@ import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.InputStreamBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.params.BasicHttpParams; +import org.apache.http.params.CoreProtocolPNames; +import org.apache.http.params.HttpParams; /** * Helpful procedures for working with services via HTTPClient @@ -64,7 +68,10 @@ public class HttpClientUtils List vals) throws ClientProtocolException, IOException { - HttpClient httpclient = new DefaultHttpClient(); + HttpParams params = new BasicHttpParams(); + params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, + HttpVersion.HTTP_1_1); + HttpClient httpclient = new DefaultHttpClient(params); HttpPost httppost = new HttpPost(postUrl); UrlEncodedFormEntity ue = new UrlEncodedFormEntity(vals, "UTF-8"); httppost.setEntity(ue); diff --git a/src/jalview/ws/jws1/JPredClient.java b/src/jalview/ws/jws1/JPredClient.java index 1a96464..df0e091 100644 --- a/src/jalview/ws/jws1/JPredClient.java +++ b/src/jalview/ws/jws1/JPredClient.java @@ -20,18 +20,28 @@ */ package jalview.ws.jws1; +import jalview.analysis.AlignSeq; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentView; +import jalview.datamodel.SeqCigar; +import jalview.datamodel.SequenceI; +import jalview.gui.AlignFrame; +import jalview.gui.Desktop; +import jalview.gui.WebserviceInfo; +import jalview.util.MessageManager; + import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.*; +import java.util.Hashtable; -import javax.swing.*; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; -import ext.vamsas.*; -import jalview.analysis.*; -import jalview.bin.*; -import jalview.datamodel.*; -import jalview.gui.*; -import jalview.util.MessageManager; +import ext.vamsas.Jpred; +import ext.vamsas.JpredServiceLocator; +import ext.vamsas.JpredSoapBindingStub; +import ext.vamsas.ServiceHandle; public class JPredClient extends WS1Client { @@ -291,7 +301,7 @@ public class JPredClient extends WS1Client WsURL = "http://www.compbio.dundee.ac.uk/JalviewWS/services/jpred"; WebserviceInfo wsInfo = new WebserviceInfo(WebServiceJobTitle, - WebServiceReference); + WebServiceReference, true); return wsInfo; } diff --git a/src/jalview/ws/jws1/WS1Client.java b/src/jalview/ws/jws1/WS1Client.java index 210e520..9001c61 100644 --- a/src/jalview/ws/jws1/WS1Client.java +++ b/src/jalview/ws/jws1/WS1Client.java @@ -92,7 +92,8 @@ public abstract class WS1Client extends WSClient implements WebserviceInfo wsInfo = null; if (!headless) { - wsInfo = new WebserviceInfo(WebServiceJobTitle, WebServiceReference); + wsInfo = new WebserviceInfo(WebServiceJobTitle, WebServiceReference, + true); } return wsInfo; } diff --git a/src/jalview/ws/jws2/AADisorderClient.java b/src/jalview/ws/jws2/AADisorderClient.java index 6c438be..929581d 100644 --- a/src/jalview/ws/jws2/AADisorderClient.java +++ b/src/jalview/ws/jws2/AADisorderClient.java @@ -351,7 +351,7 @@ public class AADisorderClient extends JabawsCalcWorker implements { if (dispFeatures) { - jalview.gui.FeatureRenderer fr = ((jalview.gui.AlignmentPanel) ap) + jalview.api.FeatureRenderer fr = ((jalview.gui.AlignmentPanel) ap) .cloneFeatureRenderer(); for (String ft : fc.keySet()) { diff --git a/src/jalview/ws/jws2/JabaWsServerQuery.java b/src/jalview/ws/jws2/JabaWsServerQuery.java index 74dce4d..b3aee55 100644 --- a/src/jalview/ws/jws2/JabaWsServerQuery.java +++ b/src/jalview/ws/jws2/JabaWsServerQuery.java @@ -180,7 +180,8 @@ public class JabaWsServerQuery implements Runnable jws2Discoverer.addInvalidServiceUrl(jwsserver); } ; - if (service != null) + if (service != null + && !Jws2InstanceFactory.ignoreService(srv.toString())) { noservices = false; Jws2Instance svc = null; @@ -212,7 +213,7 @@ public class JabaWsServerQuery implements Runnable else { jws2Discoverer.addInvalidServiceUrl(jwsserver); - Cache.log.info("Ignoring invalid Jws2 service url " + jwsserver); + Cache.log.warn("Ignoring invalid Jws2 service url " + jwsserver); } } catch (Exception e) { diff --git a/src/jalview/ws/jws2/Jws2Client.java b/src/jalview/ws/jws2/Jws2Client.java index afefe65..751d330 100644 --- a/src/jalview/ws/jws2/Jws2Client.java +++ b/src/jalview/ws/jws2/Jws2Client.java @@ -20,17 +20,6 @@ */ package jalview.ws.jws2; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; - -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; - -import compbio.metadata.Argument; import jalview.api.AlignCalcWorkerI; import jalview.bin.Cache; import jalview.gui.AlignFrame; @@ -45,6 +34,18 @@ import jalview.ws.jws2.jabaws2.Jws2Instance; import jalview.ws.params.WsParamSetI; import jalview.ws.uimodel.AlignAnalysisUIText; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JMenu; +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. * @@ -148,7 +149,7 @@ public abstract class Jws2Client extends jalview.ws.WSClient { return new WebserviceInfo(WebServiceJobTitle, WebServiceJobTitle + " using service hosted at " + serv.hosturl + "\n" - + (serv.description != null ? serv.description : "")); + + (serv.description != null ? serv.description : ""), false); } return null; } diff --git a/src/jalview/ws/jws2/Jws2Discoverer.java b/src/jalview/ws/jws2/Jws2Discoverer.java index a111d68..7a8eee9 100644 --- a/src/jalview/ws/jws2/Jws2Discoverer.java +++ b/src/jalview/ws/jws2/Jws2Discoverer.java @@ -705,7 +705,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI } else { - Cache.log.info("Ignoring duplicate url " + url + " in " + Cache.log.warn("Ignoring duplicate url " + url + " in " + JWS2HOSTURLS + " list"); } } catch (MalformedURLException ex) diff --git a/src/jalview/ws/jws2/MsaWSClient.java b/src/jalview/ws/jws2/MsaWSClient.java index 39be454..e7301a6 100644 --- a/src/jalview/ws/jws2/MsaWSClient.java +++ b/src/jalview/ws/jws2/MsaWSClient.java @@ -22,7 +22,6 @@ package jalview.ws.jws2; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentView; -import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; import jalview.gui.Desktop; import jalview.gui.JvSwingUtils; @@ -175,47 +174,20 @@ public class MsaWSClient extends Jws2Client MsaWSThread msathread = new MsaWSThread(server, preset, paramset, WsURL, wsInfo, alignFrame, WebServiceName, jobtitle, msa, submitGaps, preserveOrder, seqdataset); - wsInfo.setthisService(msathread); - - msathread.start(); - - } - - private boolean isValidAlignment(AlignmentView av) - { - int validSeqCount = 0; - List seqs = av.getVisibleAlignment('c').getSequences(); // .getSequences(); - if (seqs.size() < 2) + if (msathread.hasValidInput()) { - JOptionPane - .showMessageDialog( - alignFrame, - "A minimum of two sequences is required to perform this operation", - "Invalid selection", JOptionPane.INFORMATION_MESSAGE); - - return false; + wsInfo.setthisService(msathread); + wsInfo.setVisible(true); + msathread.start(); } - - for (SequenceI seq : seqs) + else { - - if (seq.getSequenceAsString().matches("(-*[a-zA-Z]-*){3}[a-zA-Z-]*")) - { - ++validSeqCount; - } - if (validSeqCount > 1) - { - return true; - } + JOptionPane.showMessageDialog(alignFrame, + MessageManager.getString("info.invalid_msa_input_mininfo"), + MessageManager.getString("info.invalid_msa_notenough"), + JOptionPane.INFORMATION_MESSAGE); + wsInfo.setVisible(false); } - - JOptionPane - .showMessageDialog( - alignFrame, - "All selected sequence for this job must have a minimum of \nthree non-gap character to perform this operation", - "Invalid selection", JOptionPane.INFORMATION_MESSAGE); - - return false; } public static void main(String[] args) @@ -300,7 +272,7 @@ public class MsaWSClient extends Jws2Client { AlignmentView msa = alignFrame.gatherSequencesForAlignment(); - if (msa != null && isValidAlignment(msa)) + if (msa != null) { new MsaWSClient(service, alignFrame.getTitle(), msa, withGaps, true, alignFrame.getViewport().getAlignment() @@ -324,10 +296,9 @@ public class MsaWSClient extends Jws2Client public void actionPerformed(ActionEvent e) { AlignmentView msa = alignFrame.gatherSequencesForAlignment(); - - if (msa != null && isValidAlignment(msa)) + if (msa != null) { - new MsaWSClient(service, null, null, true, alignFrame + new MsaWSClient(service, null, null, true, alignFrame .getTitle(), msa, withGaps, true, alignFrame .getViewport().getAlignment().getDataset(), alignFrame); } @@ -382,9 +353,10 @@ public class MsaWSClient extends Jws2Client AlignmentView msa = alignFrame .gatherSequencesForAlignment(); - if (msa != null && isValidAlignment(msa)) + if (msa != null) { - new MsaWSClient(service, preset, alignFrame.getTitle(), + MsaWSClient msac = new MsaWSClient(service, preset, + alignFrame.getTitle(), msa, false, true, alignFrame.getViewport() .getAlignment().getDataset(), alignFrame); } diff --git a/src/jalview/ws/jws2/MsaWSThread.java b/src/jalview/ws/jws2/MsaWSThread.java index 5e8cb98..2bae428 100644 --- a/src/jalview/ws/jws2/MsaWSThread.java +++ b/src/jalview/ws/jws2/MsaWSThread.java @@ -20,7 +20,29 @@ */ package jalview.ws.jws2; -import java.util.*; +import jalview.analysis.AlignSeq; +import jalview.bin.Cache; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentOrder; +import jalview.datamodel.AlignmentView; +import jalview.datamodel.ColumnSelection; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceI; +import jalview.gui.AlignFrame; +import jalview.gui.Desktop; +import jalview.gui.WebserviceInfo; +import jalview.util.MessageManager; +import jalview.ws.AWsJob; +import jalview.ws.JobStateSummary; +import jalview.ws.WSClientI; +import jalview.ws.jws2.dm.JabaWsParamSet; +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 compbio.data.msa.MsaWS; import compbio.metadata.Argument; @@ -28,17 +50,6 @@ import compbio.metadata.ChunkHolder; import compbio.metadata.JobStatus; import compbio.metadata.Preset; -import jalview.analysis.*; -import jalview.bin.*; -import jalview.datamodel.*; -import jalview.gui.*; -import jalview.util.MessageManager; -import jalview.ws.AWsJob; -import jalview.ws.WSClientI; -import jalview.ws.JobStateSummary; -import jalview.ws.jws2.dm.JabaWsParamSet; -import jalview.ws.params.WsParamSetI; - class MsaWSThread extends AWS2Thread implements WSClientI { boolean submitGaps = false; // pass sequences including gaps to alignment @@ -221,7 +232,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI int ow = w, nw = w; for (i = 0, w = emptySeqs.size(); i < w; i++) { - String[] es = (String[]) emptySeqs.get(i); + String[] es = emptySeqs.get(i); if (es != null && es[1] != null) { int sw = es[1].length(); @@ -252,7 +263,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI } for (i = 0, w = emptySeqs.size(); i < w; i++) { - String[] es = (String[]) emptySeqs.get(i); + String[] es = emptySeqs.get(i); if (es[1] == null) { t_alseqs[i + alseq_l] = new jalview.datamodel.Sequence(es[0], @@ -474,7 +485,7 @@ class MsaWSThread extends AWS2Thread implements WSClientI SequenceI[][] conmsa = _msa.getVisibleContigs('-'); if (conmsa != null) { - int njobs = conmsa.length; + int nvalid = 0, njobs = conmsa.length; jobs = new MsaWSJob[njobs]; for (int j = 0; j < njobs; j++) { @@ -486,6 +497,10 @@ class MsaWSThread extends AWS2Thread implements WSClientI { jobs[j] = new MsaWSJob(0, conmsa[j]); } + if (((MsaWSJob) jobs[j]).hasValidInput()) + { + nvalid++; + } ((MsaWSJob) jobs[j]).preset = preset; ((MsaWSJob) jobs[j]).arguments = paramset; ((MsaWSJob) jobs[j]).alignmentProgram = wsname; @@ -496,9 +511,20 @@ class MsaWSThread extends AWS2Thread implements WSClientI } wsinfo.setProgressText(jobs[j].getJobnum(), OutputHeader); } + validInput = nvalid > 0; } } + boolean validInput = false; + + /** + * + * @return true if the thread will perform a calculation + */ + public boolean hasValidInput() + { + return validInput; + } public boolean isCancellable() { return true; diff --git a/src/jalview/ws/jws2/jabaws2/Jws2InstanceFactory.java b/src/jalview/ws/jws2/jabaws2/Jws2InstanceFactory.java index bcc7735..696dba3 100644 --- a/src/jalview/ws/jws2/jabaws2/Jws2InstanceFactory.java +++ b/src/jalview/ws/jws2/jabaws2/Jws2InstanceFactory.java @@ -20,18 +20,21 @@ */ package jalview.ws.jws2.jabaws2; -import java.util.HashMap; - -import compbio.data.msa.JABAService; import jalview.ws.jws2.AAConClient; import jalview.ws.jws2.JPred301Client; import jalview.ws.jws2.RNAalifoldClient; import jalview.ws.uimodel.AlignAnalysisUIText; +import java.util.HashMap; +import java.util.HashSet; + +import compbio.data.msa.JABAService; + public class Jws2InstanceFactory { private static HashMap aaConGUI; + private static HashSet ignoreGUI; private static String category_rewrite(String cat_name) { return (cat_name != null && cat_name.equals("Prediction")) ? "Secondary Structure Prediction" @@ -47,12 +50,27 @@ public class Jws2InstanceFactory AAConClient.getAlignAnalysisUITest()); aaConGUI.put(compbio.ws.client.Services.RNAalifoldWS.toString(), RNAalifoldClient.getAlignAnalysisUITest()); + // disable the JPred301 client in jalview ... + ignoreGUI = new HashSet(); + ignoreGUI.add(compbio.ws.client.Services.JpredWS.toString()); aaConGUI.put(compbio.ws.client.Services.JpredWS.toString(), JPred301Client.getAlignAnalysisUITest()); } } /** + * exclusion list to avoid creating GUI elements for services we don't fully + * support + * + * @param serviceType + * @return + */ + public static boolean ignoreService(String serviceType) + { + init(); + return (ignoreGUI.contains(serviceType.toString())); + } + /** * construct a service instance and configure it with any additional * properties needed so Jalview can access it correctly * @@ -70,7 +88,6 @@ public class Jws2InstanceFactory init(); Jws2Instance svc = new Jws2Instance(jwsservers, serviceType, category_rewrite(name), description, service); - svc.aaui = aaConGUI.get(serviceType.toString()); return svc; } diff --git a/src/jalview/ws/rest/RestClient.java b/src/jalview/ws/rest/RestClient.java index cd4bb23..5ce1d5d 100644 --- a/src/jalview/ws/rest/RestClient.java +++ b/src/jalview/ws/rest/RestClient.java @@ -20,17 +20,6 @@ */ package jalview.ws.rest; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Hashtable; -import java.util.Vector; - -import javax.swing.JMenu; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; - import jalview.bin.Cache; import jalview.datamodel.AlignmentView; import jalview.gui.AlignFrame; @@ -44,6 +33,17 @@ import jalview.ws.WSClient; import jalview.ws.WSClientI; import jalview.ws.WSMenuEntryProviderI; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Hashtable; +import java.util.Vector; + +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + /** * @author JimP * @@ -107,7 +107,7 @@ public class RestClient extends WSClient implements WSClientI, if (!headless) { wsInfo = new WebserviceInfo(WebServiceJobTitle, WebServiceName + "\n" - + WebServiceReference); + + WebServiceReference, true); wsInfo.setRenderAsHtml(true); } diff --git a/test/jalview/analysis/scoremodels/FeatureScoreModelTest.java b/test/jalview/analysis/scoremodels/FeatureScoreModelTest.java new file mode 100644 index 0000000..1dbaa4a --- /dev/null +++ b/test/jalview/analysis/scoremodels/FeatureScoreModelTest.java @@ -0,0 +1,74 @@ +package jalview.analysis.scoremodels; + +import jalview.datamodel.AlignmentI; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.gui.AlignFrame; +import jalview.io.FileLoader; +import jalview.io.FormatAdapter; + +import org.junit.Assert; +import org.junit.Test; + +public class FeatureScoreModelTest +{ + public static String alntestFile = "FER1_MESCR/72-76 DVYIL\nFER1_SPIOL/71-75 DVYIL\nFER3_RAPSA/21-25 DVYVL\nFER1_MAIZE/73-77 DVYIL\n"; + + int[] sf1 = new int[] + { 74, 74, 73, 73, 23, 23, -1, -1 }; + + int[] sf2 = new int[] + { -1, -1, 74, 75, -1, -1, 76, 77 }; + + int[] sf3 = new int[] + { -1, -1, -1, -1, -1, -1, 76, 77 }; + + @Test + public void testFeatureScoreModel() throws Exception + { + AlignFrame alf = new FileLoader(false).LoadFileWaitTillLoaded(alntestFile, + FormatAdapter.PASTE); + AlignmentI al = alf.getViewport().getAlignment(); + Assert.assertEquals(4, al.getHeight()); + Assert.assertEquals(5, al.getWidth()); + for (int i = 0; i < 4; i++) + { + SequenceI ds = al.getSequenceAt(i).getDatasetSequence(); + if (sf1[i * 2] > 0) + { + ds.addSequenceFeature(new SequenceFeature("sf1", "sf1", "sf1", + sf1[i * 2], sf1[i * 2 + 1], "sf1")); + } + if (sf2[i * 2] > 0) + { + ds.addSequenceFeature(new SequenceFeature("sf2", "sf2", "sf2", + sf2[i * 2], sf2[i * 2 + 1], "sf2")); + } + if (sf3[i * 2] > 0) + { + ds.addSequenceFeature(new SequenceFeature("sf3", "sf3", "sf3", + sf3[i * 2], sf3[i * 2 + 1], "sf3")); + } + } + alf.setShowSeqFeatures(true); + alf.getFeatureRenderer().setVisible("sf1"); + alf.getFeatureRenderer().setVisible("sf2"); + alf.getFeatureRenderer().setVisible("sf3"); + alf.getFeatureRenderer().findAllFeatures(true); + Assert.assertEquals("Number of feature types", 3, alf + .getFeatureRenderer().getDisplayedFeatureTypes().length); + Assert.assertTrue(alf.getCurrentView().areFeaturesDisplayed()); + FeatureScoreModel fsm = new FeatureScoreModel(); + Assert.assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView() + .getAlignPanel())); + alf.selectAllSequenceMenuItem_actionPerformed(null); + float[][] dm = fsm.findDistances(alf.getViewport().getAlignmentView( + true)); + Assert.assertTrue("FER1_MESCR should be identical with RAPSA (2)", + dm[0][2] == 0f); + Assert.assertTrue( + "FER1_MESCR should be further from SPIOL (1) than it is from RAPSA (2)", + dm[0][1] > dm[0][2]); + + } +} diff --git a/test/jalview/datamodel/SequenceTest.java b/test/jalview/datamodel/SequenceTest.java index d9101cf..3f91710 100644 --- a/test/jalview/datamodel/SequenceTest.java +++ b/test/jalview/datamodel/SequenceTest.java @@ -88,7 +88,8 @@ public class SequenceTest /** * Tests for addAlignmentAnnotation. Note this method has the side-effect of - * setting the sequenceRef on the annotation. + * setting the sequenceRef on the annotation. Adding the same annotation twice + * should be ignored. */ @Test public void testAddAlignmentAnnotation() @@ -102,5 +103,21 @@ public class SequenceTest AlignmentAnnotation[] anns = seq.getAnnotation(); assertEquals(1, anns.length); assertSame(annotation, anns[0]); + + // re-adding does nothing + seq.addAlignmentAnnotation(annotation); + anns = seq.getAnnotation(); + assertEquals(1, anns.length); + assertSame(annotation, anns[0]); + + // an identical but different annotation can be added + final AlignmentAnnotation annotation2 = new AlignmentAnnotation("a", + "b", 2d); + seq.addAlignmentAnnotation(annotation2); + anns = seq.getAnnotation(); + assertEquals(2, anns.length); + assertSame(annotation, anns[0]); + assertSame(annotation2, anns[1]); + } } diff --git a/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java b/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java new file mode 100644 index 0000000..7dfbba1 --- /dev/null +++ b/test/jalview/ext/rbvi/chimera/ChimeraCommandsTest.java @@ -0,0 +1,92 @@ +package jalview.ext.rbvi.chimera; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.awt.Color; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +public class ChimeraCommandsTest +{ + @Test + public void testAddColourRange() + { + Map>>> map = new LinkedHashMap>>>(); + ChimeraCommands.addColourRange(map, Color.pink, 1, 2, 4, "A"); + ChimeraCommands.addColourRange(map, Color.pink, 1, 8, 8, "A"); + ChimeraCommands.addColourRange(map, Color.pink, 1, 5, 7, "B"); + ChimeraCommands.addColourRange(map, Color.red, 1, 3, 5, "A"); + ChimeraCommands.addColourRange(map, Color.red, 0, 1, 4, "B"); + ChimeraCommands.addColourRange(map, Color.orange, 0, 5, 9, "C"); + + // three colours mapped + assertEquals(3, map.keySet().size()); + + // Red has two models, Pink and Orange one each + assertEquals(2, map.get(Color.red).keySet().size()); + assertEquals(1, map.get(Color.orange).keySet().size()); + assertEquals(1, map.get(Color.pink).keySet().size()); + + // pink model 1 has two chains, red.0 / red.1 / orange.0 one each + assertEquals(2, map.get(Color.pink).get(1).keySet().size()); + assertEquals(1, map.get(Color.red).get(0).keySet().size()); + assertEquals(1, map.get(Color.red).get(1).keySet().size()); + assertEquals(1, map.get(Color.orange).get(0).keySet().size()); + + // inspect positions + List posList = map.get(Color.pink).get(1).get("A"); + assertEquals(2, posList.size()); + assertTrue(Arrays.equals(new int[] + { 2, 4 }, posList.get(0))); + assertTrue(Arrays.equals(new int[] + { 8, 8 }, posList.get(1))); + + posList = map.get(Color.pink).get(1).get("B"); + assertEquals(1, posList.size()); + assertTrue(Arrays.equals(new int[] + { 5, 7 }, posList.get(0))); + + posList = map.get(Color.red).get(0).get("B"); + assertEquals(1, posList.size()); + assertTrue(Arrays.equals(new int[] + { 1, 4 }, posList.get(0))); + + posList = map.get(Color.red).get(1).get("A"); + assertEquals(1, posList.size()); + assertTrue(Arrays.equals(new int[] + { 3, 5 }, posList.get(0))); + + posList = map.get(Color.orange).get(0).get("C"); + assertEquals(1, posList.size()); + assertTrue(Arrays.equals(new int[] + { 5, 9 }, posList.get(0))); + } + + @Test + public void testBuildColourCommands() + { + + Map>>> map = new LinkedHashMap>>>(); + ChimeraCommands.addColourRange(map, Color.blue, 0, 2, 5, "A"); + ChimeraCommands.addColourRange(map, Color.blue, 0, 7, 7, "B"); + ChimeraCommands.addColourRange(map, Color.blue, 0, 9, 23, "A"); + ChimeraCommands.addColourRange(map, Color.blue, 1, 1, 1, "A"); + ChimeraCommands.addColourRange(map, Color.blue, 1, 4, 7, "B"); + ChimeraCommands.addColourRange(map, Color.yellow, 1, 8, 8, "A"); + ChimeraCommands.addColourRange(map, Color.yellow, 1, 3, 5, "A"); + ChimeraCommands.addColourRange(map, Color.red, 0, 3, 5, "A"); + + // Colours should appear in the Chimera command in the order in which + // they were added; within colour, by model, by chain, and positions as + // added + String command = ChimeraCommands.buildColourCommands(map).get(0); + assertEquals( + "color #0000ff #0:2-5.A,9-23.A,7.B|#1:1.A,4-7.B; color #ffff00 #1:8.A,3-5.A; color #ff0000 #0:3-5.A", + command); + } +} diff --git a/test/jalview/gui/PopupMenuTest.java b/test/jalview/gui/PopupMenuTest.java index 1d219df..f7b1482 100644 --- a/test/jalview/gui/PopupMenuTest.java +++ b/test/jalview/gui/PopupMenuTest.java @@ -7,6 +7,7 @@ import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; import jalview.io.AppletFormatAdapter; +import jalview.io.FormatAdapter; import jalview.util.MessageManager; import java.awt.Component; @@ -42,7 +43,7 @@ public class PopupMenuTest @Before public void setUp() throws IOException { - alignment = new jalview.io.FormatAdapter().readFile(TEST_DATA, + alignment = new FormatAdapter().readFile(TEST_DATA, AppletFormatAdapter.PASTE, "FASTA"); AlignFrame af = new AlignFrame(alignment, 700, 500); parentPanel = new AlignmentPanel(af, af.getViewport()); @@ -83,14 +84,13 @@ public class PopupMenuTest public void testConfigureReferenceAnnotationsMenu_noReferenceAnnotations() { JMenuItem menu = new JMenuItem(); - List seqs = new ArrayList(); /* * Initial state is that sequences have annotations, and have dataset * sequences, but the dataset sequences have no annotations. Hence nothing * to add. */ - seqs = parentPanel.getAlignment().getSequences(); + List seqs = parentPanel.getAlignment().getSequences(); testee.configureReferenceAnnotationsMenu(menu, seqs); assertFalse(menu.isEnabled()); @@ -105,12 +105,12 @@ public class PopupMenuTest public void testConfigureReferenceAnnotationsMenu_alreadyAdded() { JMenuItem menu = new JMenuItem(); - List seqs = new ArrayList(); + List seqs = parentPanel.getAlignment().getSequences(); + + // make up new annotations and add to dataset sequences, sequences and + // alignment + attachReferenceAnnotations(seqs, true, true); - seqs = parentPanel.getAlignment().getSequences(); - // copy annotation from sequence to dataset - seqs.get(1).getDatasetSequence() - .addAlignmentAnnotation(seqs.get(1).getAnnotation()[0]); testee.configureReferenceAnnotationsMenu(menu, seqs); assertFalse(menu.isEnabled()); } @@ -126,28 +126,104 @@ public class PopupMenuTest { JMenuItem menu = new JMenuItem(); List seqs = parentPanel.getAlignment().getSequences(); + // make up new annotations and add to dataset sequences + attachReferenceAnnotations(seqs, false, false); + + testee.configureReferenceAnnotationsMenu(menu, seqs); + assertTrue(menu.isEnabled()); + String expected = "
    -
    Release
    -
    -
    New Features
    -
    -
    Issues Resolved
    -
    +
    + Release +
    +
    +
    + New Features +
    +
    +
    + Issues Resolved +
    +
    - 2.8.2
    18/11/2014
    + 2.8.2
    3/12/2014
    - - General + General
      +
    • Updated Java code signing certificate donated by Certum.PL.
    • +
    • Features and annotation preserved when performing pairwise + alignment
    • +
    • RNA pseudoknot annotation can be + imported/exported/displayed
    • +
    • 'colour by annotation' can colour by RNA and + protein secondary structure
    Application
      -
    • Update Jalview project format: +
    • Extract and display secondary structure for sequences with + 3D structures
    • +
    • Support for parsing RNAML
    • +
    • Annotations menu for layout
        +
      • sort sequence annotation rows by alignment
      • +
      • place sequence annotation above/below alignment + annotation
      -
    • -
    -
    Application
      +
    • Distinguish alignment and sequence associated RNA + structure in structure->view->VARNA
    • +
    • Raise dialog box if user deletes all sequences in an + alignment
    • +
    • Pressing F1 results in documentation opening twice
    • +
    • Sequence feature tooltip is wrapped
    • +
    • Double click on sequence associated annotation selects + only first column
    • +
    • Redundancy removal doesn't result in unlinked leaves + shown in tree
    • +
    • Undos after several redundancy removals don't undo + properly
    • +
    • Hide sequence doesn't hide associated annotation
    • +
    • User defined colours dialog box too big to fit on screen + and buttons not visible
    • +
    • author list isn't updated if already written to jalview + properties
    • +
    • Popup menu won't open after retrieving sequence from + database
    • +
    • File open window for associate PDB doesn't open
    • +
    • Left-then-right click on a sequence id opens a browser + search window
    • +
    • Cannot open sequence feature shading/sort popup menu in + feature settings dialog
    • +
    • better tooltip placement for some areas of Jalview desktop
    • +
    • Allow addition of JABAWS Server which doesn't pass + validation
    • +
    • Web services parameters dialog box is too large to fit on + screen
    • +
    • Muscle nucleotide alignment preset obscured by tooltip
    • +
    • JABAWS preset submenus don't contain newly defined + user preset
    • +
    • MSA web services warns user if they were launched with + invalid input
    • +
    • Jalview cannot contact DAS Registy when running on Java 8
    • +
    • + + 'Superpose with' submenu not shown when new view created +
    • -
    Applet + Deployment and Documentation +
      +
    • 2G and 1G options in launchApp have no effect on memory + allocation
    • +
    • launchApp service doesn't automatically open + www.jalview.org/examples/exampleFile.jar if no file is given
    • +
    • + + InstallAnywhere reports cannot find valid JVM when Java 1.7_055 is + available +
    • +
    Application Known issues
      +
    • + + corrupted or unreadable alignment display when scrolling alignment + to right +
    • +
    • + + retrieval fails but progress bar continues for DAS retrieval with + large number of ID +
    • +
    • + + flatfile output of visible region has incorrect sequence start/end +
    • +
    • + + rna structure consensus doesn't update when secondary + structure tracks are rearranged +
    • +
    • + + invalid rna structure positional highlighting does not highlight + position of invalid base pairs +
    • +
    • + + out of memory errors are not raised when saving jalview project + from alignment window file menu +
    • +
    • + + Switching to RNA Helices colouring doesn't propagate to + structures +
    • +
    • + + colour by RNA Helices not enabled when user created annotation + added to alignment +
    • +
    • + + Jalview icon not shown on dock in Mountain Lion/Webstart +
    • +
    Applet Known Issues +
      +
    • + + JalviewLite needs JmolApplet and VARNA-3.91 jar dependencies +
    • +
    • + + Jalview and Jmol example not compatible with IE9 +
    • + +
    • Sort by annotation score doesn't reverse order when + selected
    Add annotations for
    JMOL/secondary structure
    PBD/Temp
    "; + assertEquals(expected, menu.getToolTipText()); + } + + /** + * Test building the 'add reference annotations' menu for the case where + * several reference annotations are on the dataset and the sequences but not + * on the alignment. The menu item should be enabled, and acquire a tooltip + * which lists the annotation sources (calcIds) and type (labels). + */ + @Test + public void testConfigureReferenceAnnotationsMenu_notOnAlignment() + { + JMenuItem menu = new JMenuItem(); + List seqs = parentPanel.getAlignment().getSequences(); + + // make up new annotations and add to dataset sequences and sequences + attachReferenceAnnotations(seqs, true, false); + + testee.configureReferenceAnnotationsMenu(menu, seqs); + assertTrue(menu.isEnabled()); + String expected = "
    Add annotations for
    JMOL/secondary structure
    PBD/Temp
    "; + assertEquals(expected, menu.getToolTipText()); + } + /** + * Generate annotations and add to dataset sequences and (optionally) + * sequences and/or alignment + * + * @param seqs + * @param addToSequence + * @param addToAlignment + */ + private void attachReferenceAnnotations(List seqs, + boolean addToSequence, boolean addToAlignment) + { // PDB.secondary structure on Sequence0 AlignmentAnnotation annotation = new AlignmentAnnotation( "secondary structure", "", 0); annotation.setCalcId("PBD"); seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation); + if (addToSequence) + { + seqs.get(0).addAlignmentAnnotation(annotation); + } + if (addToAlignment) + { + this.alignment.addAnnotation(annotation); + } // PDB.Temp on Sequence1 annotation = new AlignmentAnnotation("Temp", "", 0); annotation.setCalcId("PBD"); seqs.get(1).getDatasetSequence().addAlignmentAnnotation(annotation); + if (addToSequence) + { + seqs.get(1).addAlignmentAnnotation(annotation); + } + if (addToAlignment) + { + this.alignment.addAnnotation(annotation); + } // JMOL.secondary structure on Sequence0 annotation = new AlignmentAnnotation("secondary structure", "", 0); annotation.setCalcId("JMOL"); seqs.get(0).getDatasetSequence().addAlignmentAnnotation(annotation); + if (addToSequence) + { + seqs.get(0).addAlignmentAnnotation(annotation); + } + if (addToAlignment) + { + this.alignment.addAnnotation(annotation); + } + } - testee.configureReferenceAnnotationsMenu(menu, seqs); - assertTrue(menu.isEnabled()); - String expected = "
    Add annotations for
    JMOL/secondary structure
    PBD/Temp
    "; - assertEquals(expected, menu.getToolTipText()); + /** + * Test building the 'add reference annotations' menu for the case where there + * are two alignment views: + *
      + *
    • in one view, reference annotations have been added (are on the + * datasets, sequences and alignment)
    • + *
    • in the current view, reference annotations are on the dataset and + * sequence, but not the alignment
    • + *
    + * The menu item should be enabled, and acquire a tooltip which lists the + * annotation sources (calcIds) and type (labels). + */ + @Test + public void testConfigureReferenceAnnotationsMenu_twoViews() + { } /** diff --git a/test/jalview/gui/SequenceRendererTest.java b/test/jalview/gui/SequenceRendererTest.java new file mode 100644 index 0000000..3f8b96a --- /dev/null +++ b/test/jalview/gui/SequenceRendererTest.java @@ -0,0 +1,36 @@ +package jalview.gui; + +import static org.junit.Assert.assertEquals; +import jalview.datamodel.Alignment; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceI; +import jalview.schemes.ZappoColourScheme; + +import java.awt.Color; + +import org.junit.Test; + +public class SequenceRendererTest +{ + + @Test + public void testGetResidueBoxColour_zappo() + { + SequenceI seq = new Sequence("name", "MATVLGSPRAPAFF"); // FER1_MAIZE... + AlignmentI al = new Alignment(new SequenceI[] + { seq }); + final AlignViewport av = new AlignViewport(al); + SequenceRenderer sr = new SequenceRenderer(av); + av.setGlobalColourScheme(new ZappoColourScheme()); + + // @see ResidueProperties.zappo + assertEquals(Color.pink, sr.getResidueColour(seq, 0, null)); // M + assertEquals(Color.green, sr.getResidueColour(seq, 2, null)); // T + assertEquals(Color.magenta, sr.getResidueColour(seq, 5, null)); // G + assertEquals(Color.orange, sr.getResidueColour(seq, 12, null)); // F + } + // TODO more tests for getResidueBoxColour covering groups, feature rendering, + // gaps, overview... + +} diff --git a/test/jalview/io/BioJsHTMLOutputTest.java b/test/jalview/io/BioJsHTMLOutputTest.java new file mode 100644 index 0000000..cbda794 --- /dev/null +++ b/test/jalview/io/BioJsHTMLOutputTest.java @@ -0,0 +1,47 @@ +package jalview.io; + +import jalview.datamodel.Alignment; +import jalview.datamodel.Sequence; + +import java.io.IOException; + +import org.junit.Test; + +import com.json.JSONException; + +public class BioJsHTMLOutputTest +{ + + + @Test + public void getJalviewAlignmentAsJsonString() + { + BioJsHTMLOutput bioJsHtmlOuput = new BioJsHTMLOutput(null, null); + bioJsHtmlOuput.setGlobalColorScheme("Zappo"); + + Sequence[] seqs = new Sequence[1]; + Sequence seq = new Sequence("name", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1, 26); + // SequenceFeature seqFeature = new SequenceFeature("type", "desc", + // "status", 1, 5, "jalview"); + // seq.addSequenceFeature(seqFeature); + seq.setDatasetSequence(seq); + seqs[0] = seq; + + Alignment al = new Alignment(seqs); + try + { + String generatedJson = bioJsHtmlOuput + .getJalviewAlignmentAsJsonString(al); + assert (generatedJson + .equalsIgnoreCase("{\"globalColorScheme\":\"zappo\",\"seqs\":[{\"id\":\"1\",\"start\":1,\"name\":\"name/1-26\",\"features\":[],\"seq\":\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\",\"end\":26}]}")); + System.out.println("Output : " + generatedJson); + } catch (IOException e) + { + e.printStackTrace(); + } catch (JSONException e) + { + e.printStackTrace(); + } + } + +} diff --git a/test/jalview/io/HtmlFileTest.java b/test/jalview/io/HtmlFileTest.java new file mode 100644 index 0000000..be228b8 --- /dev/null +++ b/test/jalview/io/HtmlFileTest.java @@ -0,0 +1,16 @@ +package jalview.io; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class HtmlFileTest +{ + + @Test + public void test() + { + fail("Not yet implemented"); + } + +} diff --git a/test/jalview/io/Jalview2xmlTests.java b/test/jalview/io/Jalview2xmlTests.java index 6dfa729..75626e9 100644 --- a/test/jalview/io/Jalview2xmlTests.java +++ b/test/jalview/io/Jalview2xmlTests.java @@ -20,7 +20,9 @@ */ package jalview.io; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import jalview.api.AlignmentViewPanel; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; @@ -45,7 +47,7 @@ public class Jalview2xmlTests public static void setUpBeforeClass() throws Exception { jalview.bin.Jalview.main(new String[] - { "-props", "test/src/jalview/io/testProps.jvprops" }); + { "-props", "test/jalview/io/testProps.jvprops" }); } /** @@ -237,7 +239,8 @@ public class Jalview2xmlTests @Test public void gatherViewsHere() throws Exception { - int origCount = Desktop.getAlignframes().length; + int origCount = Desktop.getAlignframes() == null ? 0 : Desktop + .getAlignframes().length; AlignFrame af = new jalview.io.FileLoader().LoadFileWaitTillLoaded( "examples/exampleFile_2_7.jar", FormatAdapter.FILE); assertTrue("Didn't read in the example file correctly.", af != null); @@ -245,4 +248,62 @@ public class Jalview2xmlTests Desktop.getAlignframes().length == 1 + origCount); } + + @Test + public void viewRefPdbAnnotation() throws Exception + { + AlignFrame af = new jalview.io.FileLoader().LoadFileWaitTillLoaded( + "examples/exampleFile_2_7.jar", FormatAdapter.FILE); + assertTrue("Didn't read in the example file correctly.", af != null); + AlignmentViewPanel sps = null; + for (AlignmentViewPanel ap : af.alignPanel.alignFrame.getAlignPanels()) + { + if ("Spinach Feredoxin Structure".equals(ap.getViewName())) + { + sps = ap; + break; + } + } + assertTrue("Couldn't find the structure view", sps != null); + SequenceI sq = sps.getAlignment().findName("1A70|"); + AlignmentAnnotation refan = null; + for (AlignmentAnnotation ra:sps.getAlignment().getAlignmentAnnotation()) + { + if (ra.graph != 0) + { + refan = ra; + break; + } + } + assertTrue("Annotation secondary structure not found.",refan!=null); + assertTrue("Couldn't find 1a70 null chain", sq != null); + // compare the manually added temperature factor annotation + // to the track automatically transferred from the pdb structure on load + for (AlignmentAnnotation ala : sq.getDatasetSequence().getAnnotation()) + { + AlignmentAnnotation alaa; + sq.addAlignmentAnnotation(alaa = new AlignmentAnnotation(ala)); + alaa.adjustForAlignment(); + if (ala.graph == refan.graph) + { + for (int p = 0; p < ala.annotations.length; p++) + { + sq.findPosition(p); + try { + assertTrue( + "Mismatch at alignment position " + p, + (alaa.annotations[p] == null && refan.annotations[p] == null) + || alaa.annotations[p].value == refan.annotations[p].value); + } + catch (NullPointerException q) + { + fail("Mismatch of alignment annotations at position " + p + + " Ref seq ann: " + refan.annotations[p] + + " alignment " + alaa.annotations[p]); + } + } + } + } + + } } diff --git a/test/jalview/io/testProps.jvprops b/test/jalview/io/testProps.jvprops new file mode 100644 index 0000000..d5a6c4c --- /dev/null +++ b/test/jalview/io/testProps.jvprops @@ -0,0 +1,84 @@ +#---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_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/ diff --git a/test/jalview/util/ColorUtilsTest.java b/test/jalview/util/ColorUtilsTest.java index da2e6ca..3bbcf27 100644 --- a/test/jalview/util/ColorUtilsTest.java +++ b/test/jalview/util/ColorUtilsTest.java @@ -39,4 +39,17 @@ public class ColorUtilsTest ColorUtils.brighterThan(darkColour)); assertNull(ColorUtils.brighterThan(null)); } + + /** + * @see http://www.rtapo.com/notes/named_colors.html + */ + @Test + public void testToTkCode() + { + assertEquals("#fffafa", ColorUtils.toTkCode(new Color(255, 250, 250))); // snow + assertEquals("#e6e6fa", ColorUtils.toTkCode(new Color(230, 230, 250))); // lavender + assertEquals("#dda0dd", ColorUtils.toTkCode(new Color(221, 160, 221))); // plum + assertEquals("#800080", ColorUtils.toTkCode(new Color(128, 0, 128))); // purple + assertEquals("#00ff00", ColorUtils.toTkCode(new Color(0, 255, 0))); // lime + } } diff --git a/utils/InstallAnywhere/Jalview.iap_xml b/utils/InstallAnywhere/Jalview.iap_xml index c938a0b..d77a93b 100755 --- a/utils/InstallAnywhere/Jalview.iap_xml +++ b/utils/InstallAnywhere/Jalview.iap_xml @@ -1,18 +1,18 @@ - - + DATE: Tue Dec 02 16:16:02 GMT 2014 --> + - - 49,53,46,48,32,80,114,111,102,101,115,115,105,111,110,97,108,32,66,117,105,108,100,32,52,53,51,56 + + 49,54,46,48,32,80,114,111,102,101,115,115,105,111,110,97,108,32,66,117,105,108,100,32,52,55,56,51 12,42,11,85,78,76,73,67,69,78,83,69,68 - 3,13,71,76,105,110,117,120,44,32,50,46,54,46,51,50,45,50,55,57,46,50,50,46,49,46,101,108,54,46,120,56,54,95,54,52,44,32,97,109,100,54,52,59,32,74,97,118,97,32,49,46,55,46,48,95,50,53,44,32,79,114,97,99,108,101,32,67,111,114,112,111,114,97,116,105,111,110,44,32,104,116,116,112,58,47,47,106,97,118,97,46,111,114,97,99,108,101,46,99,111,109,47,59,32,101,110,44,32,85,110,107,110,111,119,110,59,32,73,83,79,45,56,56,53,57,45,49 + 3,13,71,76,105,110,117,120,44,32,50,46,54,46,51,50,45,51,53,56,46,54,46,50,46,101,108,54,46,120,56,54,95,54,52,44,32,97,109,100,54,52,59,32,74,97,118,97,32,49,46,55,46,48,95,54,48,44,32,79,114,97,99,108,101,32,67,111,114,112,111,114,97,116,105,111,110,44,32,104,116,116,112,58,47,47,106,97,118,97,46,111,114,97,99,108,101,46,99,111,109,47,59,32,101,110,44,32,85,110,107,110,111,119,110,59,32,73,83,79,45,56,56,53,57,45,49 - 1,0,0,64,29,-4,96,96,80,127,118,101,93,105,116,96,121,48,48,49,56,52,67,98,113,112,112,37,82,101,96,63,55,-11,2,0,1,84,19,2,1,0,0 + 1,0,0,64,13,-64,-128,0,80,127,118,101,93,105,116,96,121,48,48,49,56,52,67,98,113,112,112,37,82,101,96,63,55,-11,2,9,1,105,27,10,1,0,0 - + false @@ -1040,112 +1040,164 @@ and any path to a file to save to the file]]> + + + + + + false + + + true + + + true + + + + + + + + + + + + false + + + + + + true + + + true + + + true + + + + + + 348699 + + + false + + + 0 + + + + + + + + + + false + + + true + + + true + + + + + + + + + + + + false + + + + + + true + + + true + + + true + + + + + + 348699 + + + false + + + 0 + + + + + + + + + + false + + + true + + + true + + + + + + + + + + + + false + + + + + + true + + + true + + + true + + + + + + 348699 + + + false + + + 0 + + + + - - - - false - - - true - - - true - - - - - - - - - - - - false - - - - - - true - - - true - - - true - - - - - - 348699 - - - false - - - 0 - - - - - - - - - - false - - - true - - - true - - - - - - - - - - - - false - - - - - - true - - - true - - - true - - - - - - 348699 - - - false - - - 0 - - - - - - @@ -2069,7 +2121,59 @@ and any path to a file to save to the file]]> - 382442 + 49768 + + + false + + + 0 + + + + + + + + + + false + + + true + + + true + + + + + + + + + + + + false + + + + + + true + + + true + + + true + + + + + + 16046 false @@ -2894,10 +2998,13 @@ Press "Done" to quit the installer.]]> true - false + true + + + - 13 + 10 21 @@ -2931,7 +3038,7 @@ Press "Done" to quit the installer.]]> true - + 10 @@ -2965,7 +3072,7 @@ Press "Done" to quit the installer.]]> true - true + false @@ -3042,13 +3149,13 @@ Press "Done" to quit the installer.]]> true - + 10 - 21 + 20 90 @@ -3079,7 +3186,7 @@ Press "Done" to quit the installer.]]> true - + 10 @@ -3144,13 +3251,13 @@ Press "Done" to quit the installer.]]> - false + true true - + 10 @@ -3215,16 +3322,19 @@ Press "Done" to quit the installer.]]> - false + true - false + true + + + 10 - 21 + 20 90 @@ -4193,7 +4303,7 @@ Press "Done" to quit the installer.]]> true - + @@ -4315,7 +4425,7 @@ Press "Done" to quit the installer.]]> - + @@ -4387,7 +4497,7 @@ Press "Done" to quit the installer.]]> - + @@ -4411,7 +4521,7 @@ Press "Done" to quit the installer.]]> - + @@ -4668,13 +4778,20 @@ Press "Done" to quit the installer.]]> 8 - 0 + 2 0 + + + + + + + @@ -4695,7 +4812,7 @@ Press "Done" to quit the installer.]]> - + @@ -5688,6 +5805,80 @@ This will remove features installed by InstallAnywhere. It will not remove file false + + + + false + + + + + + + + + + false + + + + + 1 + + + 0 + + + 0 + + + 0 + + + + + + + 1 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + true + + + true + + + false + + + false + + + false + + + + + + @@ -6185,8 +6376,11 @@ and any path to a file to read from that file]]> - - + + + + + @@ -6370,7 +6564,9 @@ and any path to a file to read from that file]]> - + + + false @@ -6872,7 +7068,6 @@ and any path to a file to read from that file]]> 0 - false @@ -6922,8 +7117,9 @@ and any path to a file to read from that file]]> - - + + + @@ -6947,6 +7143,7 @@ and any path to a file to read from that file]]> +