<td>Default is true.</td>
</tr>
<tr>
+ <td>showOccupancy</td>
+ <td>true <em>or</em> false</td>
+ <td>Default is true.</td>
+ </tr>
+ <tr>
<td>sortBy</td>
<td> Id <em>, </em> Pairwise Identity<em>, or</em> Length</td>
<td> Sorts the alignment on startup</td>
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+import java.awt.Color
+import jalview.schemes.ColourSchemeI
+import jalview.schemes.ColourSchemes
+import jalview.datamodel.AnnotatedCollectionI
+import jalview.datamodel.SequenceI
+import jalview.datamodel.SequenceCollectionI
+import jalview.util.Comparison
+
+/*
+ * Closure that defines a colour scheme where fully conserved residues are red,
+ * partly conserved (match consensus but < 100% consensus) are yellow,
+ * unconserved and gaps are white
+ */
+def conserved
+conserved = { ->
+ [
+ /*
+ * name shown in the colour menu
+ */
+ getSchemeName: { -> 'Conserved' },
+
+ /*
+ * to make a new instance for each alignment view
+ */
+ getInstance: { AnnotatedCollectionI coll, Map<SequenceI, SequenceCollectionI> map -> conserved() },
+
+ /*
+ * method only needed if colour scheme has to recalculate
+ * values when an alignment is modified
+ */
+ alignmentChanged: { AnnotatedCollectionI coll, Map<SequenceI, SequenceCollectionI> map -> },
+
+ /*
+ * determine colour for a residue at an aligned position of a
+ * sequence, given consensus residue(s) for the column and the
+ * consensus percentage identity score for the column
+ */
+ findColour: { char res, int col, SequenceI seq, String consensus, float pid ->
+ if ('a' <= res && res <= 'z')
+ {
+ res -= ('a' - 'A');
+ }
+ if (Comparison.isGap(res) || !consensus.contains(String.valueOf(res)))
+ {
+ Color.white
+ } else if (pid < 100)
+ {
+ Color.yellow
+ } else
+ {
+ Color.red
+ }
+ },
+
+ /*
+ * true means applicable to nucleotide or peptide data
+ */
+ isApplicableTo: {AnnotatedCollectionI coll -> true},
+
+ /*
+ * simple colour schemes are those that depend on the residue
+ * only (these are also available to colour structure viewers)
+ */
+ isSimple: { false }
+ ] as ColourSchemeI
+}
+
+ColourSchemes.instance.registerColourScheme(conserved())
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+import java.awt.Color
+import jalview.schemes.ColourSchemeI
+import jalview.schemes.ColourSchemes
+import jalview.datamodel.AnnotatedCollectionI
+import jalview.datamodel.SequenceI
+import jalview.datamodel.SequenceCollectionI
+import jalview.util.Comparison
+
+/*
+ * Closure that defines a colour scheme where non-consensus residues are pink,
+ * other residues (and gaps) are white
+ */
+def unconserved
+unconserved = { ->
+ [
+ /*
+ * name shown in the colour menu
+ */
+ getSchemeName: { -> 'Unconserved' },
+
+ /*
+ * to make a new instance for each alignment view
+ */
+ getInstance: { AnnotatedCollectionI coll, Map<SequenceI, SequenceCollectionI> map -> unconserved() },
+
+ /*
+ * method only needed if colour scheme has to recalculate
+ * values when an alignment is modified
+ */
+ alignmentChanged: { AnnotatedCollectionI coll, Map<SequenceI, SequenceCollectionI> map -> },
+
+ /*
+ * determine colour for a residue at an aligned position of a
+ * sequence, given consensus residue(s) for the column and the
+ * consensus percentage identity score for the column
+ */
+ findColour: { char res, int col, SequenceI seq, String consensus, float pid ->
+ if ('a' <= res && res <= 'z')
+ {
+ res -= ('a' - 'A');
+ }
+ if (Comparison.isGap(res) || consensus.contains(String.valueOf(res)))
+ {
+ Color.white
+ } else
+ {
+ Color.pink
+ }
+ },
+
+ /*
+ * true means applicable to nucleotide or peptide data
+ */
+ isApplicableTo: {AnnotatedCollectionI coll -> true},
+
+ /*
+ * simple colour schemes are those that depend on the residue
+ * only (these are also available to colour structure viewers)
+ */
+ isSimple: { false }
+ ] as ColourSchemeI
+}
+
+ColourSchemes.instance.registerColourScheme(unconserved())
+++ /dev/null
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- *
- * This file is part of Jalview.
- *
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-
-import jalview.workers.FeatureCounterI;
-import jalview.workers.AlignmentAnnotationFactory;
-
-/*
- * Example script that registers two alignment annotation calculators
- * - one that counts residues in a column with Pfam annotation
- * - one that counts only charged residues with Pfam annotation
- *
- * To try:
- * 1. load uniref50.fa from the examples folder
- * 2. load features onto it from from examples/exampleFeatures.txt
- * 3. Open this script in the Groovy console.
- * 4. Either execute this script from the console, or via Calculate->Run Groovy Script
-
- * To explore further, try changing this script to count other kinds of occurrences of
- * residue and sequence features at columns in an alignment.
- */
-
-/*
- * A closure that returns true for any Charged residue
- */
-def isCharged = { residue ->
- switch(residue) {
- case ['D', 'd', 'E', 'e', 'H', 'h', 'K', 'k', 'R', 'r']:
- return true
- }
- false
-}
-
-/*
- * A closure that returns 1 if sequence features include type 'Pfam', else 0
- * Argument should be a list of SequenceFeature
- */
-def hasPfam = { features ->
- for (sf in features)
- {
- /*
- * Here we inspect the type of the sequence feature.
- * You can also test sf.description, sf.score, sf.featureGroup,
- * sf.strand, sf.phase, sf.begin, sf.end
- * or sf.getValue(attributeName) for GFF 'column 9' properties
- */
- if ("Pfam".equals(sf.type))
- {
- return true
- }
- }
- false
-}
-
-/*
- * Closure that computes an annotation based on
- * presence of particular residues and features
- * Parameters are
- * - the name (label) for the alignment annotation
- * - the description (tooltip) for the annotation
- * - a closure (groovy function) that tests whether to include a residue
- * - a closure that tests whether to increment count based on sequence features
- */
-def getColumnCounter = { name, desc, acceptResidue, acceptFeatures ->
- [
- getName: { name },
- getDescription: { desc },
- getMinColour: { [0, 255, 255] }, // cyan
- getMaxColour: { [0, 0, 255] }, // blue
- count:
- { res, feats ->
- def c = 0
- if (acceptResidue.call(res))
- {
- if (acceptFeatures.call(feats))
- {
- c++
- }
- }
- c
- }
- ] as FeatureCounterI
-}
-
-/*
- * Define an annotation row that counts any residue with Pfam domain annotation
- */
-def pfamAnnotation = getColumnCounter("Pfam", "Count of residues with Pfam domain annotation", {true}, hasPfam)
-
-/*
- * Define an annotation row that counts charged residues with Pfam domain annotation
- */
-def chargedPfamAnnotation = getColumnCounter("Pfam charged", "Count of charged residues with Pfam domain annotation", isCharged, hasPfam)
-
-/*
- * Register the annotations
- */
-AlignmentAnnotationFactory.newCalculator(pfamAnnotation)
-AlignmentAnnotationFactory.newCalculator(chargedPfamAnnotation)
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+
+import jalview.workers.AlignmentAnnotationFactory;
+import jalview.workers.FeatureSetCounterI;
+
+/*
+ * Example script to compute two alignment annotations
+ * - count of Phosphorylation features
+ * - count of Turn features
+ * To try this, first load example file uniref50.fa and load on features file
+ * exampleFeatures.txt, before running this script
+ *
+ * The script only needs to be run once - it will be registered by Jalview
+ * and recalculated automatically when the alignment changes.
+ *
+ * Note: The feature api provided by 2.10.2 is not compatible with scripts
+ * that worked with earlier Jalview versions. Apologies for the inconvenience.
+ */
+
+def annotator =
+ [
+ getNames: { ['Phosphorylation', 'Turn'] as String[] },
+ getDescriptions: { ['Count of Phosphorylation features', 'Count of Turn features'] as String[] },
+ getMinColour: { [0, 255, 255] as int[] }, // cyan
+ getMaxColour: { [0, 0, 255] as int[] }, // blue
+ count:
+ { res, feats ->
+ int phos
+ int turn
+ for (sf in feats)
+ {
+ /*
+ * Here we inspect the type of the sequence feature.
+ * You can also test sf.description, sf.score, sf.featureGroup,
+ * sf.strand, sf.phase, sf.begin, sf.end
+ * or sf.getValue(attributeName) for GFF 'column 9' properties
+ */
+ if (sf.type.contains('TURN'))
+ {
+ turn++
+ }
+ if (sf.type.contains('PHOSPHORYLATION'))
+ {
+ phos++
+ }
+ }
+ [phos, turn] as int[]
+ }
+ ] as FeatureSetCounterI
+
+/*
+ * Register the annotation calculator with Jalview
+ */
+AlignmentAnnotationFactory.newCalculator(annotator)
+++ /dev/null
-import jalview.workers.AlignmentAnnotationFactory;
-import jalview.workers.AnnotationProviderI;
-import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.Annotation;
-import jalview.util.ColorUtils;
-import jalview.util.Comparison;
-import java.awt.Color;
-
-/*
- * Example script to compute two alignment annotations
- * - count of Phosphorylation features
- * - count of Turn features
- * To try this, first load example file uniref50.fa and load on features file
- * exampleFeatures.txt, before running this script
- *
- * The script only needs to be run once - it will be registered by Jalview
- * and recalculated automatically when the alignment changes.
- */
-
-/*
- * A closure that returns true if value includes "PHOSPHORYLATION"
- */
-def phosCounter = { type -> type.contains("PHOSPHORYLATION") }
-
-/*
- * A closure that returns true if value includes "TURN"
- */
-def turnCounter = { type -> type.contains("TURN") }
-
-/*
- * A closure that computes and returns an array of Annotation values,
- * one for each column of the alignment
- */
-def getAnnotations(al, fr, counter)
-{
- def width = al.width
- def counts = new int[width]
- def max = 0
-
- /*
- * count features in each column, record the maximum value
- */
- for (col = 0 ; col < width ; col++)
- {
- def count = 0
- for (row = 0 ; row < al.height ; row++)
- {
- seq = al.getSequenceAt(row)
- if (seq != null && col < seq.getLength())
- {
- def res = seq.getCharAt(col)
- if (!Comparison.isGap(res))
- {
- pos = seq.findPosition(col)
- features = fr.findFeaturesAtRes(seq, pos)
- for (feature in features)
- {
- if (counter.call(feature.type))
- {
- count++
- }
- }
- }
- }
- }
- counts[col] = count
- if (count > max)
- {
- max = count
- }
- }
-
- /*
- * make the Annotation objects, with a graduated colour scale
- * (from min value to max value) for the histogram bars
- */
- def zero = '0' as char
- def anns = new Annotation[width]
- for (col = 0 ; col < width ; col++)
- {
- def c = counts[col]
- if (c > 0)
- {
- Color color = ColorUtils.getGraduatedColour(c, 0, Color.cyan,
- max, Color.blue)
- anns[col] = AlignmentAnnotationFactory.newAnnotation(String.valueOf(c),
- String.valueOf(c), zero, c, color)
- }
- }
- anns
-}
-
-/*
- * Define the method that performs the calculations, and builds two
- * AlignmentAnnotation objects
- */
-def annotator =
- [ calculateAnnotation: { al, fr ->
- def phosAnns = getAnnotations(al, fr, phosCounter)
- def ann1 = AlignmentAnnotationFactory.newAlignmentAnnotation("Phosphorylation", "Count of Phosphorylation features", phosAnns)
- def turnAnns = getAnnotations(al, fr, turnCounter)
- def ann2 = AlignmentAnnotationFactory.newAlignmentAnnotation("Turn", "Count of Turn features", turnAnns)
- return [ann1, ann2]
- }
- ] as AnnotationProviderI
-
-/*
- * Register the annotation calculator with Jalview
- */
-AlignmentAnnotationFactory.newCalculator(annotator)
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+import jalview.bin.Jalview
+import jalview.workers.FeatureSetCounterI
+import jalview.workers.AlignmentAnnotationFactory
+
+/*
+ * Demonstration of FeatureSetCounterI
+ * compute annotation tracks counting number of displayed
+ * features of each type in each column
+ */
+
+/*
+ * discover features on the current view
+ */
+
+def featuresDisp=Jalview.currentAlignFrame.currentView.featuresDisplayed
+if (featuresDisp == null) {
+ print 'Need at least one feature visible on alignment'
+}
+def visibleFeatures=featuresDisp.visibleFeatures.toList()
+assert 'java.util.ArrayList' == visibleFeatures.class.name
+
+/*
+ * A closure that returns an array of features present
+ * for each feature type in visibleFeatures
+ * Argument 'features' will be a list of SequenceFeature
+ */
+def getCounts =
+ { features ->
+ int[] obs = new int[visibleFeatures.size]
+ for (sf in features)
+ {
+ /*
+ * Here we inspect the type of the sequence feature.
+ * You can also test sf.description, sf.score, sf.featureGroup,
+ * sf.strand, sf.phase, sf.begin, sf.end
+ * or sf.getValue(attributeName) for GFF 'column 9' properties
+ */
+ int pos = 0
+ for (type in visibleFeatures)
+ {
+ if (type.equals(sf.type))
+ {
+ obs[pos]++
+ }
+ pos++
+ }
+ }
+ obs
+}
+
+/*
+ * Define something that counts each visible feature type
+ */
+def columnSetCounter =
+ [
+ getNames: { visibleFeatures as String[] },
+ getDescriptions: { visibleFeatures as String[] },
+ getMinColour: { [0, 255, 255] as int[] }, // cyan
+ getMaxColour: { [0, 0, 255] as int[] }, // blue
+ count:
+ { res, feats ->
+ getCounts.call(feats)
+ }
+ ] as FeatureSetCounterI
+
+/*
+ * and register the counter
+ */
+AlignmentAnnotationFactory.newCalculator(columnSetCounter)
SEQUENCE_GROUP Group_B 1 351 2-5
SEQUENCE_GROUP Group_C 12 14 -1 seq1 seq2 seq3
PROPERTIES Group_A description=This is the description colour=Helix Propensity pidThreshold=0 outlineColour=red displayBoxes=true displayText=false colourText=false textCol1=black textCol2=black textColThreshold=0
-PROPERTIES Group_B outlineColour=red
+PROPERTIES Group_B outlineColour=red colour=None
PROPERTIES Group_C colour=Clustal
<mapID target="home" url="html/index.html" />
<mapID target="new" url="html/whatsNew.html"/>
- <mapID target="release" url="html/releases.html#Jalview.2.10.1"/>
+ <mapID target="release" url="html/releases.html#Jalview.2.10.2"/>
<mapID target="alannotation" url="html/features/annotation.html"/>
<mapID target="keys" url="html/keys.html"/>
<mapID target="newkeys" url="html/features/newkeystrokes.html"/>
<mapID target="jalarchive" url="html/features/jalarchive.html"/>
<mapID target="multipleviews" url="html/features/multipleViews.html"/>
<mapID target="splitframe" url="html/features/splitView.html"/>
+ <mapID target="splitframe.mirrorfonts" url="html/features/splitView.html#mirror"/>
<mapID target="trees" url="html/calculations/tree.html"/>
<mapID target="treeviewer" url="html/calculations/treeviewer.html"/>
<mapID target="sorting" url="html/calculations/sorting.html"/>
<mapID target="memory" url="html/memory.html" />
<mapID target="groovy" url="html/features/groovy.html" />
- <mapID target="groovy.featurecounter" url="html/groovy/featureCounter.html" />
+ <mapID target="groovy.colours" url="html/features/groovy.html#groovyColours" />
+ <mapID target="groovy.featurescounter" url="html/groovy/featuresCounter.html" />
<mapID target="privacy" url="html/privacy.html" />
<mapID target="vamsas" url="html/vamsas/index.html"/>
<mapID target="aminoAcids" url="html/misc/aminoAcids.html" />
<mapID target="homeIcon" url="icons/Home.png" />
<mapID target="printIcon" url="icons/print.png" />
<mapID target="printSetupIcon" url="icons/setup.png" />
+
+ <mapID target="overview" url="features/overview.html" />
</map>
<tocitem text="Jalview Documentation" target="home" expand="true">
<tocitem text="What's new" target="new" expand="true">
<tocitem text="Latest Release Notes" target="release"/>
+ <tocitem text="Groovy Features Counter example" target="groovy.featurescounter"/>
+ <tocitem text="Custom Colourschemes in Groovy" target="groovy.colours"/>
+ <tocitem text="Omit hidden regions in Overview" target="overview"/>
+ <tocitem text="identifers.org for URL Links" target="linksprefs" />
+ <tocitem text="New features in Split Frame View" target="splitframe.mirrorfonts" />
</tocitem>
<tocitem text="Editing Alignments" target="edit" />
</tocitem>
<tocitem text="Viewing RNA structures" target="varna" expand="false"/>
<tocitem text="Opening URLs from Jalview" target="urllinks" expand="true">
- <tocitem text="Configuring URL Links" target="urllinkspref" />
+ <tocitem text="Configuring URL Links" target="linksprefs" />
</tocitem>
<tocitem text="VAMSAS Data Exchange" target="vamsas">
<!-- what can Jalview share with other apps -->
<tocitem text="Preferences" target="preferences" />
<tocitem text="Memory Settings" target="memory" expand="false"/>
<tocitem text="Scripting with Groovy" target="groovy">
- <tocitem text="Groovy Feature Counter example" target="groovy.featurecounter"/>
+ <tocitem text="Groovy Features Counter example" target="groovy.featurescounter"/>
</tocitem>
<tocitem text="Command Line" target="commandline" expand="false">
<tocitem text="Command Line Arguments" target="clarguments" />
structure in the alignment. The regions used to calculate
the superposition will be highlighted using the 'Cartoon'
rendering style, and the remaining data shown as a chain
- trace.<br>
+ trace.<br/><br/>
</em></li>
- </ul></li>
- <li><strong>Help<br>
+ <li><strong><a name="experimental">EXPERIMENTAL FEATURES</a></strong><br/>
+ <em>
+ These are only available if the <strong>Tools→Enable
+ Experimental Features</strong> option is enabled. (Since Jalview 2.10.2)</em>
+ <ul>
+ <li><strong>Write Jalview features</strong><br /> <em>Selecting
+ this option will create new residue attributes for any
+ features currently visible in the associated alignment
+ views, allowing those positions to be selected and
+ analysed with via Chimera's 'Render by Attribute' tool
+ (found in the Tools submenu called Structure Analysis).<br />
+ <br />If you use this option, please remember to select
+ the <em>Refresh Menus</em> option in Chimera's Render by
+ Attribute dialog box in order to see the attributes
+ derived from Jalview sequence features.
+ </em><br />
+ <a href="https://issues.jalview.org/browse/JAL-2295">View
+ this function's issue in Jalview's bug tracker</a></li>
+ <li><strong>Fetch Chimera Attributes</strong><br /> <em>This
+ submenu lists available Chimera residue attributes that
+ can be imported as Jalview features on associated
+ sequences.<br />This is particularly useful for
+ transferring quantitative positional annotation. For
+ example, structure similarity for an alignment can be
+ visualised by transferring the local RMSD attributes
+ generated by Chimera's Match->Align tool onto aligned
+ sequences and displayed with a <a
+ href="featureschemes.html">Graduated feature colour
+ scheme</a>.
+ </em><a href="https://issues.jalview.org/browse/JAL-2296">View
+ this function's issue in Jalview's bug tracker</a></li>
+ </ul></li>
+ <li><strong>Help<br>
</strong>
<ul>
<li><strong>Chimera Help<br>
simplified the alignment analysis programming interface in Jalview
2.10 to make it easy for you to add your own dynamic annotation
tracks with Groovy. Have a look at the <a
- href="../groovy/featureCounter.html">featureCounter.groovy</a>
+ href="../groovy/featuresCounter.html">featuresCounter.groovy</a>
example for more information.
</p>
+ <p><a name="groovyColours"/>
+ <em>Creating custom colourschemes</em><br/>
+ You can create your own alignment colourschemes with a groovy script. We've provided two examples:<br/>
+ <ul>
+ <li><a href="http://www.jalview.org/examples/groovy/colourConserved.groovy">colourConserved.groovy</a> creates an 'Conserved' colourscheme - similar to the classic <a href="http://www.nrbsc.org/old/gfx/genedoc/">GeneDOC</a> shading model.</li>
+ <li><a href="http://www.jalview.org/examples/groovy/colourUnconserved.groovy">colourUnconserved.groovy</a> creates an 'Unconserved' colourscheme, where any unconserved residues are coloured pink.</li>
+
+ </ul>
+ </p>
</body>
</html>
<p>The red box indicates the currently viewed region of the
alignment, this may be moved by clicking and dragging with the
mouse.</p>
+ <p><strong>Right-click</strong> (or CMD-Click) to open the
+ overview's popup menu. This provides an option to include hidden
+ regions in the overview (shown as dark-grey rows and columns). <br/><br/>
+ <em>The option to include/exclude hidden regions in the
+ overview was introduced in Jalview 2.10.2</em>.
<p>
<img src="overview.gif" width="407" height="137">
</p>
<p>
<em>Show Annotations</em> - If this is selected the new window will
display an annotation panel below the sequences. This annotation
- panel may have several rows describing the whole alignment. The 3
- standard annotations <em>Conservation</em>, <em>Quality</em> and <em>Consensus</em>
- for the alignment may be shown or hidden by default using the
- checkboxes below.
+ panel may have several rows describing the whole alignment. The 4
+ standard annotations <em>Conservation</em>, <em>Quality</em>,
+ <em>Occupancy</em> and <em>Consensus</em> for the alignment may
+ be shown or hidden by default using the checkboxes adjacent and
+ below.
</p>
<p>
<em>Show group: Conservation and Consensus</em> controls the display
The <em>Custom only</em> button limits the entries in the table to
just those you have configured yourself <em>via</em> the <em>Edit
Links</em> buttons. Press <em>Show all</em> to clear any filters.
- <p>
+ </p>
+ <p>The links table is prepoulated with persistent URLs for many common
+ bioinformatics databases (since 2.10.2). These links are downloaded by Jalview from
+ the <em>identifiers.org</em> website, and the names and URLs are not
+ user editable.
<a href="../webServices/urllinks.html#urllinks">Read more about configuring
URL links.</a>
</p>
alignments, the <strong><a href="../menus/alwformat.html">"Format→Font"</a></strong>
menu option has an option 'Scale protein residues to codons'. This
option will make each protein residue the same width as a DNA
- codon (so the alignments 'line up' vertically)
+ codon (so the alignments 'line up' vertically).<br/><br/>
+ <a name="mirror"/>The 'Use same
+ font for cDNA and peptide' checkbox, when enabled, ensures that font or
+ font-size changes in either the cDNA or Protein alignment will also
+ be mirrored. (<em>Added in 2.10.2</em>)
</li>
<li><strong>"View→Protein"</strong> (in the cDNA panel)
or <strong>"View→Nucleotide"</strong> (in the protein panel)
+++ /dev/null
-<html>
-<!--
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- *
- * This file is part of Jalview.
- *
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- -->
-<head>
-<title>Extending Jalview with Groovy - Feature Counter Example</title>
-</head>
-<body>
- <p>
- <strong>Extending Jalview with Groovy - A customisable
- feature counter</strong><br /> <br />The groovy script below shows how to
- add a new calculation track to a Jalview alignment window.
- </p>
- <p>As currently written, it will add two tracks to a protein
- alignment view which count Pfam features in each column, and ones
- where a charge residue also occur.</p>
- <p>To try it for yourself:</p>
- <ol>
- <li>Copy and paste it into the groovy script console</li>
- <li>Load the example Feredoxin project (the one that opens by
- default when you first launched Jalview)</li>
- <li>Select <strong>Calculations→Execute Groovy
- Script</strong> from the alignment window's menu bar to run the script on
- the current view.
- </li>
- </ol>
- <em><a
- href="http://www.jalview.org/examples/groovy/featureCounter.groovy">http://www.jalview.org/examples/groovy/featureCounter.groovy</a>
- - rendered with <a href="http://hilite.me">hilite.me</a></em>
- <!-- HTML generated using hilite.me -->
- <div
- style="background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;">
- <pre style="margin: 0; line-height: 125%">
-<span style="color: #888888">/*</span>
-<span style="color: #888888"> * Jalview - A Sequence Alignment Editor and Viewer (Version 2.10)</span>
-<span style="color: #888888"> * Copyright (C) 2016 The Jalview Authors</span>
-<span style="color: #888888"> * </span>
-<span style="color: #888888"> * This file is part of Jalview.</span>
-<span style="color: #888888"> * </span>
-<span style="color: #888888"> * Jalview is free software: you can redistribute it and/or</span>
-<span style="color: #888888"> * modify it under the terms of the GNU General Public License </span>
-<span style="color: #888888"> * as published by the Free Software Foundation, either version 3</span>
-<span style="color: #888888"> * of the License, or (at your option) any later version.</span>
-<span style="color: #888888"> * </span>
-<span style="color: #888888"> * Jalview is distributed in the hope that it will be useful, but </span>
-<span style="color: #888888"> * WITHOUT ANY WARRANTY; without even the implied warranty </span>
-<span style="color: #888888"> * of MERCHANTABILITY or FITNESS FOR A PARTICULAR </span>
-<span style="color: #888888"> * PURPOSE. See the GNU General Public License for more details.</span>
-<span style="color: #888888"> * </span>
-<span style="color: #888888"> * You should have received a copy of the GNU General Public License</span>
-<span style="color: #888888"> * along with Jalview. If not, see <http://www.gnu.org/licenses/>.</span>
-<span style="color: #888888"> * The Jalview Authors are detailed in the 'AUTHORS' file.</span>
-<span style="color: #888888"> */</span>
-
-<span style="color: #008800; font-weight: bold">import</span> <span
- style="color: #0e84b5; font-weight: bold">jalview.workers.FeatureCounterI</span><span
- style="color: #333333">;</span>
-<span style="color: #008800; font-weight: bold">import</span> <span
- style="color: #0e84b5; font-weight: bold">jalview.workers.AlignmentAnnotationFactory</span><span
- style="color: #333333">;</span>
-
-<span style="color: #888888">/*</span>
-<span style="color: #888888"> * Example script that registers two alignment annotation calculators</span>
-<span style="color: #888888"> * - one that counts residues in a column with Pfam annotation</span>
-<span style="color: #888888"> * - one that counts only charged residues with Pfam annotation</span>
-<span style="color: #888888"> *</span>
-<span style="color: #888888"> * To try:</span>
-<span style="color: #888888"> * 1. load uniref50.fa from the examples folder</span>
-<span style="color: #888888"> * 2. load features onto it from from examples/exampleFeatures.txt</span>
-<span style="color: #888888"> * 3. Open this script in the Groovy console.</span>
-<span style="color: #888888"> * 4. Either execute this script from the console, or via Calculate->Run Groovy Script</span>
-<span style="color: #888888"> </span>
-<span style="color: #888888"> * To explore further, try changing this script to count other kinds of occurrences of </span>
-<span style="color: #888888"> * residue and sequence features at columns in an alignment.</span>
-<span style="color: #888888"> */</span>
-
-<span style="color: #888888">/*</span>
-<span style="color: #888888"> * A closure that returns true for any Charged residue</span>
-<span style="color: #888888"> */</span>
-<span style="color: #333399; font-weight: bold">def</span> isCharged <span
- style="color: #333333">=</span> <span style="color: #333333">{</span> residue <span
- style="color: #333333">-></span>
- <span style="color: #008800; font-weight: bold">switch</span><span
- style="color: #333333">(</span>residue<span
- style="color: #333333">)</span> <span style="color: #333333">{</span>
- <span style="color: #008800; font-weight: bold">case</span> <span
- style="color: #333333">[</span><span
- style="background-color: #fff0f0">'D'</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">'d'</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">'E'</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">'e'</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">'H'</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">'h'</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">'K'</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">'k'</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">'R'</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">'r'</span><span
- style="color: #333333">]:</span>
- <span style="color: #008800; font-weight: bold">return</span> <span
- style="color: #008800; font-weight: bold">true</span>
- <span style="color: #333333">}</span>
- <span style="color: #008800; font-weight: bold">false</span>
-<span style="color: #333333">}</span>
-
-<span style="color: #888888">/*</span>
-<span style="color: #888888"> * A closure that returns 1 if sequence features include type 'Pfam', else 0</span>
-<span style="color: #888888"> * Argument should be a list of SequenceFeature </span>
-<span style="color: #888888"> */</span>
-<span style="color: #333399; font-weight: bold">def</span> hasPfam <span
- style="color: #333333">=</span> <span style="color: #333333">{</span> features <span
- style="color: #333333">-></span>
- <span style="color: #008800; font-weight: bold">for</span> <span
- style="color: #333333">(</span>sf <span
- style="color: #008800; font-weight: bold">in</span> features<span
- style="color: #333333">)</span>
- <span style="color: #333333">{</span>
- <span style="color: #888888">/*</span>
-<span style="color: #888888"> * Here we inspect the type of the sequence feature.</span>
-<span style="color: #888888"> * You can also test sf.description, sf.score, sf.featureGroup,</span>
-<span style="color: #888888"> * sf.strand, sf.phase, sf.begin, sf.end</span>
-<span style="color: #888888"> * or sf.getValue(attributeName) for GFF 'column 9' properties</span>
-<span style="color: #888888"> */</span>
- <span style="color: #008800; font-weight: bold">if</span> <span
- style="color: #333333">(</span><span
- style="background-color: #fff0f0">"Pfam"</span><span
- style="color: #333333">.</span><span style="color: #0000CC">equals</span><span
- style="color: #333333">(</span>sf<span style="color: #333333">.</span><span
- style="color: #0000CC">type</span><span style="color: #333333">))</span>
- <span style="color: #333333">{</span>
- <span style="color: #008800; font-weight: bold">return</span> <span
- style="color: #008800; font-weight: bold">true</span>
- <span style="color: #333333">}</span>
- <span style="color: #333333">}</span>
- <span style="color: #008800; font-weight: bold">false</span>
-<span style="color: #333333">}</span>
-
-<span style="color: #888888">/*</span>
-<span style="color: #888888"> * Closure that computes an annotation based on </span>
-<span style="color: #888888"> * presence of particular residues and features</span>
-<span style="color: #888888"> * Parameters are</span>
-<span style="color: #888888"> * - the name (label) for the alignment annotation</span>
-<span style="color: #888888"> * - the description (tooltip) for the annotation</span>
-<span style="color: #888888"> * - a closure (groovy function) that tests whether to include a residue</span>
-<span style="color: #888888"> * - a closure that tests whether to increment count based on sequence features </span>
-<span style="color: #888888"> */</span>
-<span style="color: #333399; font-weight: bold">def</span> getColumnCounter <span
- style="color: #333333">=</span> <span style="color: #333333">{</span> name<span
- style="color: #333333">,</span> desc<span style="color: #333333">,</span> acceptResidue<span
- style="color: #333333">,</span> acceptFeatures <span
- style="color: #333333">-></span>
- <span style="color: #333333">[</span>
- <span style="color: #997700; font-weight: bold">getName:</span> <span
- style="color: #333333">{</span> name <span
- style="color: #333333">},</span>
- <span style="color: #997700; font-weight: bold">getDescription:</span> <span
- style="color: #333333">{</span> desc <span
- style="color: #333333">},</span>
- <span style="color: #997700; font-weight: bold">getMinColour:</span> <span
- style="color: #333333">{</span> <span style="color: #333333">[</span><span
- style="color: #0000DD; font-weight: bold">0</span><span
- style="color: #333333">,</span> <span
- style="color: #0000DD; font-weight: bold">255</span><span
- style="color: #333333">,</span> <span
- style="color: #0000DD; font-weight: bold">255</span><span
- style="color: #333333">]</span> <span style="color: #333333">},</span> <span
- style="color: #888888">// cyan</span>
- <span style="color: #997700; font-weight: bold">getMaxColour:</span> <span
- style="color: #333333">{</span> <span style="color: #333333">[</span><span
- style="color: #0000DD; font-weight: bold">0</span><span
- style="color: #333333">,</span> <span
- style="color: #0000DD; font-weight: bold">0</span><span
- style="color: #333333">,</span> <span
- style="color: #0000DD; font-weight: bold">255</span><span
- style="color: #333333">]</span> <span style="color: #333333">},</span> <span
- style="color: #888888">// blue</span>
- <span style="color: #997700; font-weight: bold">count:</span>
- <span style="color: #333333">{</span> res<span
- style="color: #333333">,</span> feats <span
- style="color: #333333">-></span>
- <span style="color: #333399; font-weight: bold">def</span> c <span
- style="color: #333333">=</span> <span
- style="color: #0000DD; font-weight: bold">0</span>
- <span style="color: #008800; font-weight: bold">if</span> <span
- style="color: #333333">(</span>acceptResidue<span
- style="color: #333333">.</span><span style="color: #0000CC">call</span><span
- style="color: #333333">(</span>res<span style="color: #333333">))</span>
- <span style="color: #333333">{</span>
- <span style="color: #008800; font-weight: bold">if</span> <span
- style="color: #333333">(</span>acceptFeatures<span
- style="color: #333333">.</span><span style="color: #0000CC">call</span><span
- style="color: #333333">(</span>feats<span style="color: #333333">))</span>
- <span style="color: #333333">{</span>
- c<span style="color: #333333">++</span>
- <span style="color: #333333">}</span>
- <span style="color: #333333">}</span>
- c
- <span style="color: #333333">}</span>
- <span style="color: #333333">]</span> <span
- style="color: #008800; font-weight: bold">as</span> FeatureCounterI
-<span style="color: #333333">}</span>
-
-<span style="color: #888888">/*</span>
-<span style="color: #888888"> * Define an annotation row that counts any residue with Pfam domain annotation</span>
-<span style="color: #888888"> */</span>
-<span style="color: #333399; font-weight: bold">def</span> pfamAnnotation <span
- style="color: #333333">=</span> getColumnCounter<span
- style="color: #333333">(</span><span
- style="background-color: #fff0f0">"Pfam"</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">"Count of residues with Pfam domain annotation"</span><span
- style="color: #333333">,</span> <span style="color: #333333">{</span><span
- style="color: #008800; font-weight: bold">true</span><span
- style="color: #333333">},</span> hasPfam<span
- style="color: #333333">)</span>
-
-<span style="color: #888888">/*</span>
-<span style="color: #888888"> * Define an annotation row that counts charged residues with Pfam domain annotation</span>
-<span style="color: #888888"> */</span>
-<span style="color: #333399; font-weight: bold">def</span> chargedPfamAnnotation <span
- style="color: #333333">=</span> getColumnCounter<span
- style="color: #333333">(</span><span
- style="background-color: #fff0f0">"Pfam charged"</span><span
- style="color: #333333">,</span> <span
- style="background-color: #fff0f0">"Count of charged residues with Pfam domain annotation"</span><span
- style="color: #333333">,</span> isCharged<span
- style="color: #333333">,</span> hasPfam<span
- style="color: #333333">)</span>
-
-<span style="color: #888888">/*</span>
-<span style="color: #888888"> * Register the annotations</span>
-<span style="color: #888888"> */</span>
-AlignmentAnnotationFactory<span style="color: #333333">.</span><span
- style="color: #0000CC">newCalculator</span><span
- style="color: #333333">(</span>pfamAnnotation<span
- style="color: #333333">)</span>
-AlignmentAnnotationFactory<span style="color: #333333">.</span><span
- style="color: #0000CC">newCalculator</span><span
- style="color: #333333">(</span>chargedPfamAnnotation<span
- style="color: #333333">)</span>
-</pre>
- </div>
-</body>
-</html>
--- /dev/null
+<html>
+<!--
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ -->
+<head>
+<title>Extending Jalview with Groovy - Feature Counter Example</title>
+</head>
+<body>
+ <p>
+ <strong>Extending Jalview with Groovy - A customisable
+ feature counter</strong><br /> <br />The groovy script below shows how to
+ add a new calculation track to a Jalview alignment window.
+ </p>
+ <p>As currently written, it will add two tracks to a protein
+ alignment view which count Pfam features in each column, and ones
+ where a charge residue also occur.</p>
+ <p>To try it for yourself:</p>
+ <ol>
+ <li>Copy and paste it into the groovy script console</li>
+ <li>Load the example Feredoxin project (the one that opens by
+ default when you first launched Jalview)</li>
+ <li>Select <strong>Calculations→Execute Groovy
+ Script</strong> from the alignment window's menu bar to run the script on
+ the current view.
+ </li>
+ </ol>
+ <strong>Please note: The 2.10.2 feature counting interface is not compatible with earlier versions.</strong><br/><br/>
+ <em><a
+ href="http://www.jalview.org/examples/groovy/featuresCounter.groovy">http://www.jalview.org/examples/groovy/featuresCounter.groovy</a>
+ - rendered with <a href="http://hilite.me">hilite.me</a></em>
+ <!-- HTML generated using hilite.me --><div style="background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #408080; font-style: italic">/*</span>
+<span style="color: #408080; font-style: italic"> * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)</span>
+<span style="color: #408080; font-style: italic"> * Copyright (C) $$Year-Rel$$ The Jalview Authors</span>
+<span style="color: #408080; font-style: italic"> * </span>
+<span style="color: #408080; font-style: italic"> * This file is part of Jalview.</span>
+<span style="color: #408080; font-style: italic"> * </span>
+<span style="color: #408080; font-style: italic"> * Jalview is free software: you can redistribute it and/or</span>
+<span style="color: #408080; font-style: italic"> * modify it under the terms of the GNU General Public License </span>
+<span style="color: #408080; font-style: italic"> * as published by the Free Software Foundation, either version 3</span>
+<span style="color: #408080; font-style: italic"> * of the License, or (at your option) any later version.</span>
+<span style="color: #408080; font-style: italic"> * </span>
+<span style="color: #408080; font-style: italic"> * Jalview is distributed in the hope that it will be useful, but </span>
+<span style="color: #408080; font-style: italic"> * WITHOUT ANY WARRANTY; without even the implied warranty </span>
+<span style="color: #408080; font-style: italic"> * of MERCHANTABILITY or FITNESS FOR A PARTICULAR </span>
+<span style="color: #408080; font-style: italic"> * PURPOSE. See the GNU General Public License for more details.</span>
+<span style="color: #408080; font-style: italic"> * </span>
+<span style="color: #408080; font-style: italic"> * You should have received a copy of the GNU General Public License</span>
+<span style="color: #408080; font-style: italic"> * along with Jalview. If not, see <http://www.gnu.org/licenses/>.</span>
+<span style="color: #408080; font-style: italic"> * The Jalview Authors are detailed in the 'AUTHORS' file.</span>
+<span style="color: #408080; font-style: italic"> */</span>
+
+<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">jalview.workers.AlignmentAnnotationFactory</span><span style="color: #666666">;</span>
+<span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">jalview.workers.FeatureSetCounterI</span><span style="color: #666666">;</span>
+
+<span style="color: #408080; font-style: italic">/*</span>
+<span style="color: #408080; font-style: italic"> * Example script to compute two alignment annotations</span>
+<span style="color: #408080; font-style: italic"> * - count of Phosphorylation features</span>
+<span style="color: #408080; font-style: italic"> * - count of Turn features</span>
+<span style="color: #408080; font-style: italic"> * To try this, first load example file uniref50.fa and load on features file</span>
+<span style="color: #408080; font-style: italic"> * exampleFeatures.txt, before running this script</span>
+<span style="color: #408080; font-style: italic"> *</span>
+<span style="color: #408080; font-style: italic"> * The script only needs to be run once - it will be registered by Jalview</span>
+<span style="color: #408080; font-style: italic"> * and recalculated automatically when the alignment changes.</span>
+<span style="color: #408080; font-style: italic"> * </span>
+<span style="color: #408080; font-style: italic"> * Note: The feature api provided by 2.10.2 is not compatible with scripts</span>
+<span style="color: #408080; font-style: italic"> * that worked with earlier Jalview versions. Apologies for the inconvenience.</span>
+<span style="color: #408080; font-style: italic"> */</span>
+
+<span style="color: #B00040">def</span> annotator <span style="color: #666666">=</span>
+ <span style="color: #666666">[</span>
+ <span style="color: #A0A000">getNames:</span> <span style="color: #666666">{</span> <span style="color: #666666">[</span><span style="color: #BA2121">'Phosphorylation'</span><span style="color: #666666">,</span> <span style="color: #BA2121">'Turn'</span><span style="color: #666666">]</span> <span style="color: #008000; font-weight: bold">as</span> String<span style="color: #666666">[]</span> <span style="color: #666666">},</span>
+ <span style="color: #A0A000">getDescriptions:</span> <span style="color: #666666">{</span> <span style="color: #666666">[</span><span style="color: #BA2121">'Count of Phosphorylation features'</span><span style="color: #666666">,</span> <span style="color: #BA2121">'Count of Turn features'</span><span style="color: #666666">]</span> <span style="color: #008000; font-weight: bold">as</span> String<span style="color: #666666">[]</span> <span style="color: #666666">},</span>
+ <span style="color: #A0A000">getMinColour:</span> <span style="color: #666666">{</span> <span style="color: #666666">[0,</span> <span style="color: #666666">255,</span> <span style="color: #666666">255]</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #B00040">int</span><span style="color: #666666">[]</span> <span style="color: #666666">},</span> <span style="color: #408080; font-style: italic">// cyan</span>
+ <span style="color: #A0A000">getMaxColour:</span> <span style="color: #666666">{</span> <span style="color: #666666">[0,</span> <span style="color: #666666">0,</span> <span style="color: #666666">255]</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #B00040">int</span><span style="color: #666666">[]</span> <span style="color: #666666">},</span> <span style="color: #408080; font-style: italic">// blue</span>
+ <span style="color: #A0A000">count:</span>
+ <span style="color: #666666">{</span> res<span style="color: #666666">,</span> feats <span style="color: #666666">-></span>
+ <span style="color: #B00040">int</span> phos
+ <span style="color: #B00040">int</span> turn
+ <span style="color: #0000FF">for</span> <span style="color: #666666">(</span>sf <span style="color: #008000; font-weight: bold">in</span> feats<span style="color: #666666">)</span>
+ <span style="color: #666666">{</span>
+ <span style="color: #408080; font-style: italic">/*</span>
+<span style="color: #408080; font-style: italic"> * Here we inspect the type of the sequence feature.</span>
+<span style="color: #408080; font-style: italic"> * You can also test sf.description, sf.score, sf.featureGroup,</span>
+<span style="color: #408080; font-style: italic"> * sf.strand, sf.phase, sf.begin, sf.end</span>
+<span style="color: #408080; font-style: italic"> * or sf.getValue(attributeName) for GFF 'column 9' properties</span>
+<span style="color: #408080; font-style: italic"> */</span>
+ <span style="color: #008000; font-weight: bold">if</span> <span style="color: #666666">(</span>sf<span style="color: #666666">.</span><span style="color: #7D9029">type</span><span style="color: #666666">.</span><span style="color: #7D9029">contains</span><span style="color: #666666">(</span><span style="color: #BA2121">'TURN'</span><span style="color: #666666">))</span>
+ <span style="color: #666666">{</span>
+ turn<span style="color: #666666">++</span>
+ <span style="color: #666666">}</span>
+ <span style="color: #008000; font-weight: bold">if</span> <span style="color: #666666">(</span>sf<span style="color: #666666">.</span><span style="color: #7D9029">type</span><span style="color: #666666">.</span><span style="color: #7D9029">contains</span><span style="color: #666666">(</span><span style="color: #BA2121">'PHOSPHORYLATION'</span><span style="color: #666666">))</span>
+ <span style="color: #666666">{</span>
+ phos<span style="color: #666666">++</span>
+ <span style="color: #666666">}</span>
+ <span style="color: #666666">}</span>
+ <span style="color: #666666">[</span>phos<span style="color: #666666">,</span> turn<span style="color: #666666">]</span> <span style="color: #008000; font-weight: bold">as</span> <span style="color: #B00040">int</span><span style="color: #666666">[]</span>
+ <span style="color: #666666">}</span>
+ <span style="color: #666666">]</span> <span style="color: #008000; font-weight: bold">as</span> FeatureSetCounterI
+
+<span style="color: #408080; font-style: italic">/*</span>
+<span style="color: #408080; font-style: italic"> * Register the annotation calculator with Jalview</span>
+<span style="color: #408080; font-style: italic"> */</span>
+AlignmentAnnotationFactory<span style="color: #666666">.</span><span style="color: #7D9029">newCalculator</span><span style="color: #666666">(</span>annotator<span style="color: #666666">)</span>
+</pre></div>
+</body>
+</html>
the <a href="../features/groovy.html">Groovy Console</a> for
interactive scripting.
</em><strong><br></strong></li>
+ <li><strong>Enable Experimental Features</strong> <em>Enable or disable <a href="../whatsNew.html#experimental">features still under development</a> in Jalview's user interface. This setting is remembered in your preferences.</em>
</ul></li>
<li><strong>Vamsas</strong> <em>For more details, read the
-->
<head>
<title>Release History</title>
+<style>
+ul {
+ /* remove bullets, narrower indent */
+ list-style-type: none;
+ margin:0;
+ padding-left: 10px;
+ padding-bottom: 4px;
+}
+
+li {
+ /* separate the items from eachother */
+ margin-left: -3px;
+ padding-bottom: 3px;
+ padding-left: 6px;
+}
+li:before {
+ /* doesnt get processed in javahelp */
+ content: '\00b7 ';
+ padding: 3px;
+ margin-left: -14px;
+}
+
+</style>
</head>
<body>
<p>
<tr>
<td width="60" nowrap>
<div align="center">
+ <strong><a name="Jalview.2.10.2">2.10.2</a><br />
+ <em>30/5/2017</em></strong>
+ </div>
+ </td>
+ <td><div align="left">
+ <em>General</em>
+ <ul>
+ <li><!-- JAL-2360,JAL-2371, -->More robust colours and shader model for alignments and groups</li>
+ <li><!-- JAL-384 -->Custom shading schemes created via groovy scripts</li>
+ </ul>
+ <em>Application</em>
+ <ul>
+ <li>
+ <!-- JAL-2447 -->
+ Experimental Features Checkbox in Desktop's Tools
+ menu to hide or show untested features in the application.
+ </li>
+ <li><!-- JAL-1476 -->Warning in alignment status bar when there are not enough columns to superimpose structures in Chimera</li>
+ <li><!-- JAL-1596 -->Faster Chimera/Jalview communication by file-based command exchange</li>
+ <li><!-- JAL-2316, -->URLs for viewing database cross-references provided by identifiers.org and the EMBL-EBI's MIRIAM DB</li>
+
+ </ul>
+ <em>Experimental features</em>
+ <ul>
+ <li>
+ <!-- JAL-2295, JAL-2296 -->New entries in the Chimera menu
+ to transfer Chimera's structure attributes as Jalview
+ features, and vice-versa.
+ </li>
+ </ul>
+ <em>Applet</em>
+ <ul>
+ <li><!-- --></li>
+ </ul>
+ <em>Test Suite</em>
+ <li><!-- JAL-2474 -->Added PrivelegedAccessor to test suite</li>
+ <li><!-- JAL-2326 -->Prevent or clear modal dialogs raised during tests</li>
+ <li><!-- -->
+ </ul>
+ </div></td><td><div align="left">
+ <em>General</em>
+ <ul>
+ <li>
+ <!-- JAL-2398, -->Fixed incorrect value in BLOSUM 62 score
+ matrix - C->R should be '3'<br />Old matrix restored with
+ this one-line groovy script:<br />jalview.schemes.ResidueProperties.BLOSUM62[4][1]=3
+ </li>
+ <li>
+ <!-- JAL-2397 -->Fixed Jalview's treatment of gaps in PCA
+ and substitution matrix based Tree calculations.<br />In
+ earlier versions of Jalview, gaps matching gaps were
+ penalised, and gaps matching non-gaps penalised even more.
+ In the PCA calculation, gaps were actually treated as
+ non-gaps - so different costs were applied, which mean't
+ Jalview's PCAs were different to those produced by
+ SeqSpace.<br />Jalview now treats gaps in the same way as
+ SeqSpace (ie it scores them as 0). To restore pre-2.10.2
+ behaviour<br />
+ jalview.viewmodel.PCAModel.scoreGapAsAny=true // for
+ 2.10.1 mode<br />
+ jalview.viewmodel.PCAModel.scoreGapAsAny=false // to
+ restore 2.10.2 mode
+ </li>
+ <li><!-- JAL-2346 -->Reopening Colour by annotation dialog doesn't reselect a specific sequence's associated annotation after it was used for colouring a view</li>
+ <li><!-- JAL-2430 -->Hidden regions in alignment views are not coloured in linked structure views</li>
+ <li><!-- JAL-2419 -->Current selection lost if popup menu opened on a region of alignment without groups</li>
+ <li><!-- JAL-2374 -->Popup menu not always shown for regions of an alignment with overlapping groups</li>
+ <li><!-- JAL-2310 -->Finder double counts if both a sequence's name and description match</li>
+ <li><!-- JAL-2370 -->Hiding column selection containing two hidden regions results in incorrect hidden regions</li>
+ <li><!-- JAL-2377 -->PCA calculation could hang when generating output report when working with highly redundant alignments</li>
+ <li><!-- JAL-2365 -->Cannot configure feature colours with lightGray or darkGray via features file</li>
+ <li><!-- JAL-2421 -->Overview window visible region moves erratically when hidden rows or columns are present</li>
+ <li><!-- JAL-2362 -->Per-residue colourschemes applied via the Structure Viewer's colour menu don't correspond to sequence colouring</li>
+ <li><!-- JAL-2405 -->Protein specific colours only offered in colour and group colour menu for protein alignments</li>
+ <li><!-- JAL-2386 -->'Apply to all groups' setting when changing colour does not apply Conservation slider value to all groups</li>
+ <li><!-- JAL-2385 -->Colour threshold slider doesn't update to reflect currently selected view or group's shading thresholds</li>
+ <li><!-- JAL-2373 -->Percentage identity and conservation menu items do not show a tick or allow shading to be disabled</li>
+ <li><!-- JAL-2385 -->Conservation shading or PID threshold lost when base colourscheme changed if slider not visible</li>
+ </ul>
+ <em>Application</em>
+ <ul>
+ <li><!-- JAL-2401 -->Easier creation of colours for all 'Lower case' residues (button in colourscheme editor debugged and new documentation and tooltips added)</li>
+ <li><!-- JAL-2399-->Text colour threshold's 'Cancel' button doesn't restore group-specific text colour thresholds</li>
+ <li><!-- JAL-2243 -->Feature settings panel does not update as new features are added to alignment</li>
+ <li><!-- JAL-2436 -->Structure viewer's View -> Colour By view selection menu changes colours of alignment views</li>
+ <li><!-- JAL-2366 -->Proxy server address and port always appear enabled in Preferences->Connections</li>
+ <li><!-- JAL-2426 -->Spurious exceptions in console raised from alignment calculation workers after alignment has been closed</li>
+ <li><!-- JAL-1608 -->Typo in selection popup menu - Create groups now 'Create Group'</li>
+ <li><!-- JAL-1608 -->CMD/CTRL and G or Shift G for Create/Undefine group doesn't always work</li>
+ <li><!-- JAL-2464 -->Tree Viewer's Print Dialog doesn't get shown again after pressing 'Cancel'</li>
+ <li><!-- JAL-2461 -->DAS registry not found exceptions removed from console output</li>
+ <li><!-- JAL-2383 -->Above PID colour threshold not recovered when alignment view imported from project</li>
+
+ </ul>
+ <em>Applet</em>
+ <ul>
+ <li><!-- JAL-2442 -->Features not rendered as transparent on overview or linked structure view</li>
+ <li><!-- JAL-2372 -->Colour group by conservation doesn't work (since 2.8)</li>
+ </ul>
+ <em>New Known Issues</em>
+ <ul>
+ <li></li>
+ </ul>
+
+ </div>
+ <tr>
+ <td width="60" nowrap>
+ <div align="center">
<strong><a name="Jalview.2.10.1">2.10.1</a><br />
<em>29/11/2016</em></strong>
</div>
<!--JAL-2332 -->Attempting to view structure for Hen
lysozyme results in a PDB Client error dialog box
</li>
+ <li>
+ <!-- JAL-2319 -->Structure View's mapping report switched ranges for PDB and sequence for SIFTS</li>
+ <!-- JAL-2319 -->SIFTS 'Not_Observed' residues mapped to non-existant coordindate data</li>
</ul>
<!-- <em>New Known Issues</em>
<ul>
<em>Adding additional links</em><br /> You can configure your own
links via the Jalview <a href="../features/preferences.html#links"><strong>Preferences</strong></a>
dialog. Jalview also provides persistent URLs for many common
- bioinformatics databases. These links are downloaded by Jalview from
+ bioinformatics databases (since 2.10.2). These links are downloaded by Jalview from
the <em>identifiers.org</em> website, and the names and URLs are not
user editable.
</p>
<p>
- <em>Creating your own URL link</em> URL links are specified as a
+ <em>Creating your own URL link</em> <br/>URL links are specified as a
template containing special tokens that Jalview will replace with
the Sequence ID or Database Accession of the sequence when you
double click on its ID or open it's <strong>Link</strong> submenu.
Swissprot = http://www.expasy.org/uniprot/$SEQUENCE_ID$ <br> </pre>
<p>
Links will also be made for any database cross references associated
- with the sequence where the database name exactly matches a URL link
- name. In this case, the $DB_ACCESSION$ string will be replaced with
+ with the sequence for any link templates whose name begins with the database name.
+ In this case, the $DB_ACCESSION$ string will be replaced with
the accession string for the database cross-reference, rather than
the sequence ID for the sequence (<em>since Jalview 2.10.1</em>).
+ <br /> <em>For example: to create a link for viewing MACiE records
+ from PDB Entries, create a new custom link entry with the name
+ "PDB in MACiE", and link URL template:
+ <pre>https://www.ebi.ac.uk/thornton-srv/databases/cgi-bin/MACiE/index.pl?query_pdb=1&pdb=$DBACCESSION$</pre>
+ <br />The sequence ID popup menu for seuqences with a PDB entry
+ will now show 'PDB in MACiE|1xyz..' links in the <strong>links</strong>
+ submenu.
+ </em>
</p>
<p>
<strong><a name="warning">Warning dialog about updating
</head>
<body>
<p>
- <strong>What's new in Jalview 2.10.1 ?</strong>
+ <strong>What's new in Jalview 2.10.2 ?</strong>
</p>
<p>
- Jalview 2.10.1 was released on 29th November 2016. Full details are
- in the <a href="releases.html#Jalview.2.10.1">Jalview 2.10.1
- Release Notes</a>, but the highlights are below. This is also the
- first release to include contributions from Kira Mourão, who
- joined Jalview's core development team in October 2016.
+ Full details about Jalview 2.10.2 are in the <a
+ href="releases.html#Jalview.2.10.2"> Release Notes</a>, but the
+ highlights are below.
</p>
<ul>
- <li><strong>More memory efficient</strong><br />We've slimmed
- down the consensus analysis data structures used by Jalview so
- even wider alignments can be worked with.</li>
- <li><strong>Select highlighted region</strong><br />Press 'B'
- or use the new menu option in the alignment window's Select menu
- to mark columns containing highlighted regions generated from
- structure selections, mouse-overs, or resulting from a Find
- operation.</li>
- <li><strong>New custom link mechanism for opening URLs
- for database cross references.</strong><br /> If you have customised URL
- links in your Jalview preferences, then you may already have seen
- the <a href="#warning"> warning dialog (see below).</a></li>
- <li><strong>New command line export option for BioJS
- MSAviewer</strong><br />A number of small bugs with the HTML export
- functions from the Jalview desktop were also fixed.</li>
- <li><strong>Small but significant changes to the
- physicochemical properties and consensus calculations</strong><br />Threonine
- is no longer considered a non-hydrophobic residue in the protein
- conservation calculation, and minor bugs addressed in PID and
- consensus colouring.</li>
- <li><strong>Correct display of disulphide bond
- features</strong><br /> In linked structure views, Jalview would
- highlight all residues between in addition to the two linked
- cysteines. The 'select columns by feature' function in the feature
- settings would also select all intermediate columns.
+ <li>
+ <li>New preferences for <a href="webServices/urllinks.html">opening
+ web pages for database cross-references</a> via the UK Elixir's
+ EMBL-EBI's MIRIAM database and identifiers.org services.
+ </li>
</ul>
-
<p>
- <strong><a name="warning">Warning dialog about updating
- your configured URL links</a></strong><br /> In the desktop prior to Jalview
- 2.10.1, the only way to configure custom links for a particular
- database cross-reference for a sequence was to give it a name that <em>exactly</em>
- matched the database source, and a regular expression for filtering
- out any spurious matches generated when the custom linked was tested
- against the Sequence's ID string. Since the introduction of the
- $DB_ACCESSION$ token, however, $SEQUENCE_ID$ will not be used for
- database cross-reference accession strings, and if you have custom
- links configured, Jalview will raise a warning message so let you
- know that you may need to update your links to use $DB_ACCESSION$.
+ <strong><a name="experimental">Experimental Features</a></strong>
</p>
+ <p>This release of Jalview includes a new option in the Jalview Desktop
+ that allows you to try out features that are still in development. To
+ access the features described below, please first enable the
+ <strong>Tools→Enable Experimental Features</strong> option, and then restart Jalview.
+ </p>
+ <ul>
+ <li><em>Annotation transfer between Chimera and Jalview</em><br />Two
+ <a href="features/chimera.html#experimental">new entries in the Chimera viewer's Chimera menu</a> allow positional
+ annotation to be exchanged between Chimera and Jalview.
+ </li>
+ </ul>
</body>
</html>
action.merge_results = Merge Results
action.load_scheme = Load scheme
action.save_scheme = Save scheme
+label.scheme_changed = Changes to scheme ''{0}'' have not been saved.<br><br>Save changes, or continue without saving to make a new colour scheme.
+label.save_changes = Save Changes
+label.dont_save_changes = Don't Save
action.save_image = Save Image
action.paste = Paste
action.show_html_source = Show HTML Source
action.scale_right = Scale Right
action.by_tree_order = By Tree Order
action.sort = Sort
-action.calculate_tree = Calculate Tree
+action.calculate_tree = Calculate Tree...
+action.calculate_tree_pca = Calculate Tree or PCA...
action.help = Help
action.by_annotation = By Annotation...
action.invert_sequence_selection = Invert Sequence Selection
label.principal_component_analysis = Principal Component Analysis
label.average_distance_identity = Average Distance Using % Identity
label.neighbour_joining_identity = Neighbour Joining Using % Identity
+label.choose_calculation = Choose Calculation
label.treecalc_title = {0} Using {1}
label.tree_calc_av = Average Distance
label.tree_calc_nj = Neighbour Joining
label.score_model_pid = % Identity
label.score_model_blosum62 = BLOSUM62
label.score_model_pam250 = PAM 250
+label.score_model_smithwatermanscore = Score between two sequences aligned with Smith-Waterman with default Peptide/Nucleotide matrix
+label.score_model_sequencefeaturesimilarity = Distance measure of average number of features not shared at sequence positions
label.score_model_conservation = Physicochemical property conservation
label.score_model_enhconservation = Physicochemical property conservation
label.status_bar = Status bar
label.out_to_textbox = Output to Textbox
+label.occupancy = Occupancy
# delete Clustal - use FileFormat name instead
label.clustal = Clustal
# label.colourScheme_<schemeName> as in JalviewColourScheme
label.set_this_label_text = set this label text
label.sequences_from = Sequences from {0}
label.successfully_loaded_file = Successfully loaded file {0}
+label.successfully_loaded_matrix = Successfully loaded score matrix {0}
label.successfully_saved_to_file_in_format = Successfully saved to file: {0} in {1} format.
label.copied_sequences_to_clipboard = Copied {0} sequences to clipboard.
label.check_file_matches_sequence_ids_alignment = Check that the file matches sequence IDs in the alignment.
label.remove_user_defined_colour = Remove user defined colour
label.you_must_select_least_two_sequences = You must select at least 2 sequences.
label.invalid_selection = Invalid Selection
-label.principal_component_analysis_must_take_least_four_input_sequences = Principal component analysis must take\nat least 4 input sequences.
label.sequence_selection_insufficient = Sequence selection insufficient
-label.you_need_more_two_sequences_selected_build_tree = You need to have more than two sequences selected to build a tree!
+label.you_need_at_least_n_sequences = You need to select at least {0} sequences
label.not_enough_sequences = Not enough sequences
label.selected_region_to_tree_may_only_contain_residues_or_gaps = The selected region to create a tree may\nonly contain residues or gaps.\nTry using the Pad function in the edit menu,\nor one of the multiple sequence alignment web services.
label.sequences_selection_not_aligned = Sequences in selection are not aligned
-label.sequences_must_be_aligned_before_creating_tree = The sequences must be aligned before creating a tree.\nTry using the Pad function in the edit menu,\n or one of the multiple sequence alignment web services.
-label.sequences_not_aligned = Sequences not aligned
label.problem_reading_tree_file = Problem reading tree file
label.possible_problem_with_tree_file = Possible problem with tree file
label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation = Please select at least three bases in at least one sequence in order to perform a cDNA translation.
label.show_labels = Show labels
action.background_colour = Background Colour...
label.associate_nodes_with = Associate Nodes With
-label.jalview_pca_calculation = Jalview PCA Calculation
label.link_name = Link Name
label.pdb_file = PDB file
label.colour_with_jmol = Colour with Jmol
label.error_whilst_saving_current_state_to = Error whilst saving current state to {0}
label.error_whilst_loading_project_from = Error whilst loading project from {0}
label.couldnt_load_project = Couldn't load project
-label.pca_sequences_not_aligned = The sequences must be aligned before calculating PCA.\nTry using the Pad function in the edit menu,\nor one of the multiple sequence alignment web services.
label.invalid_name_preset_exists = Invalid name - preset already exists.
label.invalid_name = Invalid name
label.set_proxy_settings = Please set up your proxy settings in the 'Connections' tab of the Preferences window
label.save_as_html = Save as HTML
label.recently_opened = Recently Opened
label.blasting_for_unidentified_sequence_jobs_running = BLASTing for unidentified sequences - {0} jobs running.
+label.tree = Tree
label.tree_from = Tree from {0}
label.webservice_job_title = {0} using {1}
label.select_visible_region_of = selected {0} region of {1}
label.updating_vamsas_session = Updating vamsas session
label.loading_file = Loading File: {0}
label.edit_params = Edit {0}
+label.as_percentage = As Percentage
error.not_implemented = Not implemented
error.no_such_method_as_clone1_for = No such method as clone1 for {0}
error.null_from_clone1 = Null from clone1!
label.start_jalview = Start Jalview
label.biojs_html_export = BioJS
label.scale_as_cdna = Scale protein residues to codons
+label.font_as_cdna = Use same font for cDNA and peptide
label.scale_protein_to_cdna = Scale Protein to cDNA
label.scale_protein_to_cdna_tip = Make protein residues same width as codons in split frame views
info.select_annotation_row = Select Annotation Row
label.output_seq_details = Output Sequence Details to list all database references
label.urllinks = Links
label.default_cache_size = Default Cache Size
-action.clear_cached_items = Clear Cached Items
\ No newline at end of file
+action.clear_cached_items = Clear Cached Items
+label.togglehidden = Show hidden regions
+label.quality_descr = Alignment Quality based on Blosum62 scores
+label.conservation_descr = Conservation of total alignment less than {0}% gaps
+label.consensus_descr = PID
+label.complement_consensus_descr = PID for cDNA
+label.strucconsensus_descr = PID for base pairs
+label.occupancy_descr = Number of aligned positions
+label.show_experimental = Enable experimental features
+label.show_experimental_tip = Enable any new and currently 'experimental' features (see Latest Release Notes for details)
+label.warning_hidden = Warning: {0} {1} is currently hidden
action.merge_results = Unificar resultados
action.load_scheme = Cargar esquema
action.save_scheme = Guardar esquema
+label.scheme_changed = Cambios en el esquema ''{0}'' no se han guardado.<br><br>Guardar cambios, o continuar sin guardar para hacer un nuevo esquema.
+label.save_changes = Guardar cambios
+label.dont_save_changes = No guardar
action.save_image = Guardar imagen
action.paste = Pegar
action.show_html_source = Mostrar código HTML
action.scale_right = Escala derecha
action.by_tree_order = Por orden del árbol
action.sort = Ordenar
-action.calculate_tree = Calcular árbol
+action.calculate_tree = Calcular árbol...
+action.calculate_tree_pca = Calcular árbol o ACP...
action.help = Ayuda
action.by_annotation = Por anotación...
action.invert_sequence_selection = Invertir selección de secuencias
label.principal_component_analysis = Análisis del Componente Principal
label.average_distance_identity = Distancia Media Usando % de Identidad
label.neighbour_joining_identity = Unir vecinos utilizando % de Identidad
+label.choose_calculation = Elegir el cálculo
label.treecalc_title = {0} utilizando {1}
label.tree_calc_av = Distancia media
label.tree_calc_nj = Unir vecinos
label.score_model_pid = % Identidad
label.score_model_blosum62 = BLOSUM62
label.score_model_pam250 = PAM 250
+label.score_model_smithwatermanscore = Puntuación entre secuencias alineadas por Smith-Waterman con matriz por defecto proteica / nucleotídica
+label.score_model_sequencefeaturesimilarity = Medida de distancia por cuenta promedia de características no compartidas en posiciones de secuencia
label.score_model_conservation = Conservación de las propiedades físico-químicas
label.score_model_enhconservation = Conservación de las propiedades físico-químicas
label.status_bar = Barra de estado
label.out_to_textbox = Generar cuadro de texto
+label.occupancy = Ocupación
label.clustal = Clustal
# label.colourScheme_<schemeName> as in JalviewColourScheme
label.colourScheme_clustal = Clustalx
label.set_this_label_text = fijar como etiqueta
label.sequences_from = Secuencias de {0}
label.successfully_loaded_file = Fichero cargado exitosamente {0}
+label.successfully_loaded_matrix = Matriz cargada exitosamente {0}
label.successfully_saved_to_file_in_format = Guardado exitosamente en el fichero: {0} en formato {1}.
label.copied_sequences_to_clipboard = Copiadas {0} secuencias en el portapapeles.
label.check_file_matches_sequence_ids_alignment = Comprobar que el fichero coincide con el ID de la secuencia en el alineamiento.
label.remove_user_defined_colour = Eliminar el color definido por el usuario
label.you_must_select_least_two_sequences = Debes seleccionar al menos 2 secuencias.
label.invalid_selection = Selección inválida
-label.principal_component_analysis_must_take_least_four_input_sequences = El an\u00E1lisis de la componente principal debe tomar\nal menos 4 secuencias de entrada.
label.sequence_selection_insufficient = Selección de secuencias insuficiente
-label.you_need_more_two_sequences_selected_build_tree = necesitas seleccionar más de dos secuencias para construir un árbol!
+label.you_need_at_least_n_sequences = Necesitas seleccionar al menos {0} secuencias
label.not_enough_sequences = No suficientes secuencias
label.selected_region_to_tree_may_only_contain_residues_or_gaps = La regi\u00F3n seleccionada para construir un \u00E1rbol puede\ncontener s\u00F3lo residuos o espacios.\nPrueba usando la funci\u00F3n Pad en el men\u00FA de edici\u00F3n,\n o uno de los m\u00FAltiples servicios web de alineamiento de secuencias.
label.sequences_selection_not_aligned = Las secuencias seleccionadas no están alineadas
-label.sequences_must_be_aligned_before_creating_tree = Las secuencias deben estar alineadas antes de crear el \u00E1rbol.\nPrueba usando la funci\u00F3n Pad en el men\u00FA de editar,\n o uno de los m\u00FAltiples servicios web de alineamiento de secuencias.
-label.sequences_not_aligned = Secuencias no alineadas
label.problem_reading_tree_file = Problema al leer el fichero del árbol
label.possible_problem_with_tree_file = Posible problema con el fichero del árbol
label.select_at_least_three_bases_in_at_least_one_sequence_to_cDNA_translation = Por favor seleccionar al menos tres bases de al menos una secuencia para poder realizar la traducción de cDNA.
label.selection_output_command = Seleccionar salida - {0}
label.annotation_for_displayid = <p><h2>Anotación para {0} </h2></p><p>
label.pdb_sequence_mapping = PDB - Mapeado de secuencia
-label.pca_details = detalles de la PCA
+label.pca_details = detalles de la ACP
label.redundancy_threshold_selection = Selección del umbral de redundancia
label.user_defined_colours = Colores definidos del usuario
label.jalviewLite_release = JalviewLite - versión {0}
label.no_features_added_to_this_alignment = No hay funciones asociadas a este alineamiento!!
label.features_can_be_added_from_searches_1 = (Las funciones pueden ser añadidas de búsquedas o
label.features_can_be_added_from_searches_2 = de ficheros de funciones Jalview / GFF)
-label.calculating_pca= Calculando PCA
+label.calculating_pca= Calculando ACP
label.jalview_cannot_open_file = Jalview no puede abrir el fichero
label.jalview_applet = Aplicación Jalview
label.loading_data = Cargando datos
label.set_as_default = Establecer por defecto
label.show_labels = Mostrar etiquetas
label.associate_nodes_with = Asociar nodos con
-label.jalview_pca_calculation = Cálculo del PCA por Jalview
label.link_name = Nombre del enalce
label.pdb_file = Fichero PDB
label.colour_with_jmol = Colorear con Jmol
-label.align_structures = Alinear estructuras
label.jmol = Jmol
label.sort_alignment_by_tree = Ordenar alineamiento por árbol
label.mark_unlinked_leaves = Marcar las hojas como no enlazadas
label.error_whilst_saving_current_state_to = Error mientras se guardaba el estado a {0}
label.error_whilst_loading_project_from = Error cargando el proyecto desde {0}
label.couldnt_load_project = No es posible cargar el proyecto
-label.pca_sequences_not_aligned = Las secuencias deben estar alineadas antes de calcular el PCA.\nPruebe a utilizar la funci\u00F3n de rellenar huecos en el men\u00FA Editar,\no cualquiera de los servicios web de alineamiento m\u00FAltiple.
label.invalid_name_preset_exists = Nombre no válido - esta preconfiguración ya existe.
label.invalid_name = Nombre no válido
label.set_proxy_settings = Por favor, configure su proxy en la pestaña 'Conexiones' de la ventana de Preferencia
label.save_as_html = Guardar como HTML
label.recently_opened = Abiertos recientemente
label.blasting_for_unidentified_sequence_jobs_running = Ejecutando BLAST de las secuencias no indentificadas - {0} trabajos en marcha.
+label.tree = Árbol
label.tree_from = Árbol de {0}
label.webservice_job_title = {0} usando {1}
label.select_visible_region_of = seleccionada {0} región de {1}
label.updating_vamsas_session = Actualizando sesión VAMSAS
label.loading_file = Cargando fichero: {0}
label.edit_params = Editar {0}
+label.as_percentage = Como Porcentaje
error.not_implemented = No implementado
error.no_such_method_as_clone1_for = No existe ese método como un clone1 de {0}
error.null_from_clone1 = Nulo de clone1!
label.empty_alignment_job = Trabajo de alineamiento vacío
label.add_new_sbrs_service = Añadir un nuevo SBRS
label.edit_sbrs_entry = Editar entrada SBRS
-label.pca_recalculating = Recalculando PCA
-label.pca_calculating = Calculando PCA
+label.pca_recalculating = Recalculando ACP
+label.pca_calculating = Calculando ACP
label.select_foreground_colour = Escoger color del primer plano
label.select_colour_for_text = Seleccione el color del texto
label.adjunst_foreground_text_colour_threshold = Ajustar el umbral del color del texto en primer plano
label.nuc_alignment_colour=Color del Alineamiento Nucleotídico
label.copy_format_from=Copiar formato de
label.chimera=Chimera
+label.create_chimera_attributes = Escribir características de Jalview
+label.create_chimera_attributes_tip = Establecer atributos en Chimera para características visibles
+label.attributes_set = {0} valores de atributos establecidos en Chimera
label.open_split_window=Abrir ventana dividida
label.open_split_window?=¿Quieres abrir ventana dividida, con cDNA y proteína vinculadas?
status.searching_for_pdb_structures=Buscando Estructuras PDB
label.scale_as_cdna=Adaptar residuos proteicos a los codones
+label.font_as_cdna=Utilizar la misma fuente para nucleotídos y proteicos
action.export_hidden_sequences=Exportar Secuencias Ocultas
action.export_hidden_columns=Exportar Columnas Ocultas
label.found_structures_summary=Resumen de Estructuras Encontradas
label.select_pdb_file=Seleccionar Fichero PDB
label.structures_filter=Filtro de Estructuras
label.scale_protein_to_cdna=Adaptar proteína a cDNA
+label.scale_protein_to_cdna_tip=Hacer a los residuos de proteínas de la misma anchura que los codones en ventanas divididas
status.loading_cached_pdb_entries=Cargando Entradas PDB en Caché
label.select=Seleccionar :
label.select_by_annotation=Seleccionar/Ocultar Columnas por Anotación
info.change_threshold_mode_to_enable=Cambiar Modo de Umbral para Habilitar
label.separate_multiple_query_values=Introducir uno o mas {0}s separados por punto y coma ";"
label.let_chimera_manage_structure_colours=Deja que Chimera maneje colores de estructuras
+label.fetch_chimera_attributes = Buscar atributos desde Chimera
+label.fetch_chimera_attributes_tip = Copiar atributo de Chimera a característica de Jalview
label.view_rna_structure=Estructura 2D VARNA
-label.scale_protein_to_cdna_tip=Hacer a los residuos de proteínas de la misma anchura que los codones en ventanas divididas
label.colour_with_chimera=Colorear con Chimera
+label.superpose_structures = Superponer estructuras
+error.superposition_failed = Superposición fallido: {0}
+label.insufficient_residues = Residuos alineados ({0}) insuficentes para superponer
label.show_pdbstruct_dialog=Datos de Estructura 3D...
label.hide_all=Ocultar todos
label.invert=Invertir
label.alpha_helix=Hélice Alfa
label.chimera_help=Ayuda para Chimera
label.find_tip=Buscar alineamiento, selección o IDs de secuencia para una subsecuencia (sin huecos)
-label.structure_viewer=Visualizador de estructura for defecto
+label.structure_viewer=Visualizador de estructura por defecto
label.embbed_biojson=Incrustar BioJSON al exportar HTML
label.transparency_tip=Ajustar la transparencia a "ver a través" los colores de las características.
label.choose_annotations=Escoja anotaciones
label.invalid_name = Nombre inválido !
label.output_seq_details = Seleccionar Detalles de la secuencia para ver todas
label.urllinks = Enlaces
+label.quality_descr = Calidad de alineamiento basándose en puntuación Blosum62
+label.conservation_descr = Conservación del alineamiento total menos de {0}% huecos
+label.consensus_descr = % Identidad
+label.complement_consensus_descr = % Identidad para cDNA
+label.strucconsensus_descr = % Identidad para pares de bases
+label.occupancy_descr = Número de posiciones alineadas
+label.togglehidden = Show hidden regions
+label.warning_hidden = Advertencia: {0} {1} está actualmente oculto
--- /dev/null
+ScoreMatrix BLOSUM62
+#
+# The BLOSUM62 substitution matrix, as at https://www.ncbi.nlm.nih.gov/Class/FieldGuide/BLOSUM62.txt
+# The first line declares a ScoreMatrix with the name BLOSUM62 (shown in menus)
+#
+# Scores are not symbol case sensitive, unless column(s) are provided for lower case characters
+# The 'guide symbol' at the start of each row of score values is optional
+# Values may be integer or floating point, delimited by tab, space, comma or combinations
+#
+ A R N D C Q E G H I L K M F P S T W Y V B Z X *
+A 4 -1 -2 -2 0 -1 -1 0 -2 -1 -1 -1 -1 -2 -1 1 0 -3 -2 0 -2 -1 0 -4
+R -1 5 0 -2 -3 1 0 -2 0 -3 -2 2 -1 -3 -2 -1 -1 -3 -2 -3 -1 0 -1 -4
+N -2 0 6 1 -3 0 0 0 1 -3 -3 0 -2 -3 -2 1 0 -4 -2 -3 3 0 -1 -4
+D -2 -2 1 6 -3 0 2 -1 -1 -3 -4 -1 -3 -3 -1 0 -1 -4 -3 -3 4 1 -1 -4
+C 0 -3 -3 -3 9 -3 -4 -3 -3 -1 -1 -3 -1 -2 -3 -1 -1 -2 -2 -1 -3 -3 -2 -4
+Q -1 1 0 0 -3 5 2 -2 0 -3 -2 1 0 -3 -1 0 -1 -2 -1 -2 0 3 -1 -4
+E -1 0 0 2 -4 2 5 -2 0 -3 -3 1 -2 -3 -1 0 -1 -3 -2 -2 1 4 -1 -4
+G 0 -2 0 -1 -3 -2 -2 6 -2 -4 -4 -2 -3 -3 -2 0 -2 -2 -3 -3 -1 -2 -1 -4
+H -2 0 1 -1 -3 0 0 -2 8 -3 -3 -1 -2 -1 -2 -1 -2 -2 2 -3 0 0 -1 -4
+I -1 -3 -3 -3 -1 -3 -3 -4 -3 4 2 -3 1 0 -3 -2 -1 -3 -1 3 -3 -3 -1 -4
+L -1 -2 -3 -4 -1 -2 -3 -4 -3 2 4 -2 2 0 -3 -2 -1 -2 -1 1 -4 -3 -1 -4
+K -1 2 0 -1 -3 1 1 -2 -1 -3 -2 5 -1 -3 -1 0 -1 -3 -2 -2 0 1 -1 -4
+M -1 -1 -2 -3 -1 0 -2 -3 -2 1 2 -1 5 0 -2 -1 -1 -1 -1 1 -3 -1 -1 -4
+F -2 -3 -3 -3 -2 -3 -3 -3 -1 0 0 -3 0 6 -4 -2 -2 1 3 -1 -3 -3 -1 -4
+P -1 -2 -2 -1 -3 -1 -1 -2 -2 -3 -3 -1 -2 -4 7 -1 -1 -4 -3 -2 -2 -1 -2 -4
+S 1 -1 1 0 -1 0 0 0 -1 -2 -2 0 -1 -2 -1 4 1 -3 -2 -2 0 0 0 -4
+T 0 -1 0 -1 -1 -1 -1 -2 -2 -1 -1 -1 -1 -2 -1 1 5 -2 -2 0 -1 -1 0 -4
+W -3 -3 -4 -4 -2 -2 -3 -2 -2 -3 -2 -3 -1 1 -4 -3 -2 11 2 -3 -4 -3 -2 -4
+Y -2 -2 -2 -3 -2 -1 -2 -3 2 -1 -1 -2 -1 3 -3 -2 -2 2 7 -1 -3 -2 -1 -4
+V 0 -3 -3 -3 -1 -2 -2 -3 -3 3 1 -2 1 -1 -2 -2 0 -3 -1 4 -3 -2 -1 -4
+B -2 -1 3 4 -3 0 1 -1 0 -3 -4 0 -3 -3 -2 0 -1 -4 -3 -3 4 1 -1 -4
+Z -1 0 0 1 -3 3 4 -2 0 -3 -3 1 -1 -3 -1 0 -1 -3 -2 -2 1 4 -1 -4
+X 0 -1 -1 -1 -2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -2 0 0 -2 -1 -1 -1 -1 -1 -4
+* -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 1
--- /dev/null
+#
+# Source: http://www.genome.jp/dbget-bin/www_bget?aaindex:HENS920103
+#
+H HENS920103
+D BLOSUM80 substitution matrix (Henikoff-Henikoff, 1992)
+R PMID:1438297
+A Henikoff, S. and Henikoff, J.G.
+T Amino acid substitution matrices from protein blocks
+J Proc. Natl. Acad. Sci. USA 89, 10915-10919 (1992)
+* matrix in 1/3 Bit Units
+M rows = ARNDCQEGHILKMFPSTWYV, cols = ARNDCQEGHILKMFPSTWYV
+ 7.
+ -3. 9.
+ -3. -1. 9.
+ -3. -3. 2. 10.
+ -1. -6. -5. -7. 13.
+ -2. 1. 0. -1. -5. 9.
+ -2. -1. -1. 2. -7. 3. 8.
+ 0. -4. -1. -3. -6. -4. -4. 9.
+ -3. 0. 1. -2. -7. 1. 0. -4. 12.
+ -3. -5. -6. -7. -2. -5. -6. -7. -6. 7.
+ -3. -4. -6. -7. -3. -4. -6. -7. -5. 2. 6.
+ -1. 3. 0. -2. -6. 2. 1. -3. -1. -5. -4. 8.
+ -2. -3. -4. -6. -3. -1. -4. -5. -4. 2. 3. -3. 9.
+ -4. -5. -6. -6. -4. -5. -6. -6. -2. -1. 0. -5. 0. 10.
+ -1. -3. -4. -3. -6. -3. -2. -5. -4. -5. -5. -2. -4. -6. 12.
+ 2. -2. 1. -1. -2. -1. -1. -1. -2. -4. -4. -1. -3. -4. -2. 7.
+ 0. -2. 0. -2. -2. -1. -2. -3. -3. -2. -3. -1. -1. -4. -3. 2. 8.
+ -5. -5. -7. -8. -5. -4. -6. -6. -4. -5. -4. -6. -3. 0. -7. -6. -5. 16.
+ -4. -4. -4. -6. -5. -3. -5. -6. 3. -3. -2. -4. -3. 4. -6. -3. -3. 3. 11.
+ -1. -4. -5. -6. -2. -4. -4. -6. -5. 4. 1. -4. 1. -2. -4. -3. 0. -5. -3. 7.
+//
--- /dev/null
+ScoreMatrix DNA
+#
+# A DNA substitution matrix.
+# This is an ad-hoc matrix which, in addition to penalising mutations between the common
+# nucleotides (ACGT), includes T/U equivalence in order to allow both DNA and/or RNA.
+# In addition, it encodes weak equivalence between R and Y with AG and CTU, respectively,
+# and N is allowed to match any other base weakly.
+# This matrix also includes I (Inosine) and X (Xanthine), but encodes them to weakly match
+# any of (ACGTU), and unfavourably match each other.
+#
+# The first line declares a ScoreMatrix with the name DNA (shown in menus)
+# Scores are not case sensitive, unless column(s) are provided for lower case characters
+#
+# Values may be integer or floating point, delimited by tab, space, comma or combinations
+#
+ A C G T U I X R Y N -
+A 10 -8 -8 -8 -8 1 1 1 -8 1 1
+C -8 10 -8 -8 -8 1 1 -8 1 1 1
+G -8 -8 10 -8 -8 1 1 1 -8 1 1
+T -8 -8 -8 10 10 1 1 -8 1 1 1
+U -8 -8 -8 10 10 1 1 -8 1 1 1
+I 1 1 1 1 1 10 0 0 0 1 1
+X 1 1 1 1 1 0 10 0 0 1 1
+R 1 -8 1 -8 -8 0 0 10 -8 1 1
+Y -8 1 -8 1 1 0 0 -8 10 1 1
+N 1 1 1 1 1 1 1 1 1 10 1
+- 1 1 1 1 1 1 1 1 1 1 1
--- /dev/null
+ScoreMatrix PAM250
+#
+# The PAM250 substitution matrix
+# The first line declares a ScoreMatrix with the name PAM250 (shown in menus)
+# Scores are not case sensitive, unless column(s) are provided for lower case characters
+# Values may be integer or floating point, delimited by tab, space, comma or combinations
+#
+ A R N D C Q E G H I L K M F P S T W Y V B Z X *
+A 2 -2 0 0 -2 0 0 1 -1 -1 -2 -1 -1 -3 1 1 1 -6 -3 0 0 0 0 -8
+R -2 6 0 -1 -4 1 -1 -3 2 -2 -3 3 0 -4 0 0 -1 2 -4 -2 -1 0 -1 -8
+N 0 0 2 2 -4 1 1 0 2 -2 -3 1 -2 -3 0 1 0 -4 -2 -2 2 1 0 -8
+D 0 -1 2 4 -5 2 3 1 1 -2 -4 0 -3 -6 -1 0 0 -7 -4 -2 3 3 -1 -8
+C -2 -4 -4 -5 12 -5 -5 -3 -3 -2 -6 -5 -5 -4 -3 0 -2 -8 0 -2 -4 -5 -3 -8
+Q 0 1 1 2 -5 4 2 -1 3 -2 -2 1 -1 -5 0 -1 -1 -5 -4 -2 1 3 -1 -8
+E 0 -1 1 3 -5 2 4 0 1 -2 -3 0 -2 -5 -1 0 0 -7 -4 -2 3 3 -1 -8
+G 1 -3 0 1 -3 -1 0 5 -2 -3 -4 -2 -3 -5 0 1 0 -7 -5 -1 0 0 -1 -8
+H -1 2 2 1 -3 3 1 -2 6 -2 -2 0 -2 -2 0 -1 -1 -3 0 -2 1 2 -1 -8
+I -1 -2 -2 -2 -2 -2 -2 -3 -2 5 2 -2 2 1 -2 -1 0 -5 -1 4 -2 -2 -1 -8
+L -2 -3 -3 -4 -6 -2 -3 -4 -2 2 6 -3 4 2 -3 -3 -2 -2 -1 2 -3 -3 -1 -8
+K -1 3 1 0 -5 1 0 -2 0 -2 -3 5 0 -5 -1 0 0 -3 -4 -2 1 0 -1 -8
+M -1 0 -2 -3 -5 -1 -2 -3 -2 2 4 0 6 0 -2 -2 -1 -4 -2 2 -2 -2 -1 -8
+F -3 -4 -3 -6 -4 -5 -5 -5 -2 1 2 -5 0 9 -5 -3 -3 0 7 -1 -4 -5 -2 -8
+P 1 0 0 -1 -3 0 -1 0 0 -2 -3 -1 -2 -5 6 1 0 -6 -5 -1 -1 0 -1 -8
+S 1 0 1 0 0 -1 0 1 -1 -1 -3 0 -2 -3 1 2 1 -2 -3 -1 0 0 0 -8
+T 1 -1 0 0 -2 -1 0 0 -1 0 -2 0 -1 -3 0 1 3 -5 -3 0 0 -1 0 -8
+W -6 2 -4 -7 -8 -5 -7 -7 -3 -5 -2 -3 -4 0 -6 -2 -5 17 0 -6 -5 -6 -4 -8
+Y -3 -4 -2 -4 0 -4 -4 -5 0 -1 -1 -4 -2 7 -5 -3 -3 0 10 -2 -3 -4 -2 -8
+V 0 -2 -2 -2 -2 -2 -2 -1 -2 4 2 -2 2 -1 -1 -1 0 -6 -2 4 -2 -2 -1 -8
+B 0 -1 2 3 -4 1 3 0 1 -2 -3 1 -2 -4 -1 0 0 -5 -3 -2 3 2 -1 -8
+Z 0 0 1 3 -5 3 3 0 2 -2 -3 0 -2 -5 0 0 -1 -6 -4 -2 2 3 -1 -8
+X 0 -1 0 -1 -3 -1 -1 -1 -1 -1 -1 -1 -1 -2 -1 0 0 -4 -2 -1 -1 -1 -1 -8
+* -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 1
colourBySequence();
- int max = -10;
+ float max = -10;
int maxchain = -1;
int pdbstart = 0;
int pdbend = 0;
colourBySequence();
- int max = -10;
+ float max = -10;
int maxchain = -1;
int pdbstart = 0;
int pdbend = 0;
*/
package jalview.analysis;
-import java.util.Arrays;
-import java.util.Hashtable;
-import java.util.List;
-
import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.util.MappingUtils;
import jalview.util.QuickSort;
+import java.awt.Color;
+import java.util.Arrays;
+import java.util.Hashtable;
+import java.util.List;
+
/**
* Takes in a vector or array of sequences and column start and column end and
* returns a new Hashtable[] of size maxSeqLength, if Hashtable not supplied.
// always set ranges again
gaprow.graphMax = nseq;
gaprow.graphMin = 0;
+ double scale = 0.8/nseq;
for (int i = startCol; i < endCol; i++)
{
ProfileI profile = profiles.get(i);
final int gapped = profile.getNonGapped();
- String description = String.valueOf(gapped);
+ String description = "" + gapped;
- gaprow.annotations[i] = new Annotation(description, description,
- '\0',
- gapped);
+ gaprow.annotations[i] = new Annotation("", description,
+ '\0', gapped, jalview.util.ColorUtils.bleachColour(
+ Color.DARK_GRAY, (float) scale * gapped));
}
}
*/
package jalview.analysis;
+import jalview.analysis.scoremodels.PIDModel;
+import jalview.analysis.scoremodels.ScoreMatrix;
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.analysis.scoremodels.SimilarityParams;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.Mapping;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
-import jalview.schemes.ResidueProperties;
-import jalview.schemes.ScoreMatrix;
import jalview.util.Comparison;
import jalview.util.Format;
import jalview.util.MapList;
private static final String NEWLINE = System.lineSeparator();
- static String[] dna = { "A", "C", "G", "T", "-" };
+ float[][] score;
- // "C", "T", "A", "G", "-"};
- static String[] pep = { "A", "R", "N", "D", "C", "Q", "E", "G", "H", "I",
- "L", "K", "M", "F", "P", "S", "T", "W", "Y", "V", "B", "Z", "X", "-" };
+ float[][] E;
- int[][] score;
-
- int[][] E;
-
- int[][] F;
+ float[][] F;
int[][] traceback;
int count;
/** DOCUMENT ME!! */
- public int maxscore;
+ public float maxscore;
float pid;
int gapExtend = 20;
- int[][] lookup = ResidueProperties.getBLOSUM62();
-
- String[] intToStr = pep;
-
- int defInt = 23;
-
StringBuffer output = new StringBuffer();
- String type;
+ String type; // AlignSeq.PEP or AlignSeq.DNA
+
+ private ScoreMatrix scoreMatrix;
- private int[] charToInt;
+ private static final int GAP_INDEX = -1;
/**
* Creates a new AlignSeq object.
*
- * @param s1
- * DOCUMENT ME!
- * @param s2
- * DOCUMENT ME!
- * @param type
- * DOCUMENT ME!
+ * @param s1 first sequence for alignment
+ * @param s2 second sequence for alignment
+ * @param type molecule type, either AlignSeq.PEP or AlignSeq.DNA
*/
public AlignSeq(SequenceI s1, SequenceI s2, String type)
{
- SeqInit(s1, s1.getSequenceAsString(), s2, s2.getSequenceAsString(),
+ seqInit(s1, s1.getSequenceAsString(), s2, s2.getSequenceAsString(),
type);
}
public AlignSeq(SequenceI s1, String string1, SequenceI s2,
String string2, String type)
{
- SeqInit(s1, string1.toUpperCase(), s2, string2.toUpperCase(), type);
+ seqInit(s1, string1.toUpperCase(), s2, string2.toUpperCase(), type);
}
/**
*
* @return DOCUMENT ME!
*/
- public int getMaxScore()
+ public float getMaxScore()
{
return maxscore;
}
}
/**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public SequenceI getS1()
- {
- return s1;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public SequenceI getS2()
- {
- return s2;
- }
-
- /**
*
* @return aligned instance of Seq 1
*/
* @param type
* DNA or PEPTIDE
*/
- public void SeqInit(SequenceI s1, String string1, SequenceI s2,
+ public void seqInit(SequenceI s1, String string1, SequenceI s2,
String string2, String type)
{
this.s1 = s1;
this.s2 = s2;
setDefaultParams(type);
- SeqInit(string1, string2);
- }
-
- /**
- * Construct score matrix for sequences with custom substitution matrix
- *
- * @param s1
- * - sequence 1
- * @param string1
- * - string to use for s1
- * @param s2
- * - sequence 2
- * @param string2
- * - string to use for s2
- * @param scoreMatrix
- * - substitution matrix to use for alignment
- */
- public void SeqInit(SequenceI s1, String string1, SequenceI s2,
- String string2, ScoreMatrix scoreMatrix)
- {
- this.s1 = s1;
- this.s2 = s2;
- setType(scoreMatrix.isDNA() ? AlignSeq.DNA : AlignSeq.PEP);
- lookup = scoreMatrix.getMatrix();
+ seqInit(string1, string2);
}
/**
* @param string1
* @param string2
*/
- private void SeqInit(String string1, String string2)
+ private void seqInit(String string1, String string2)
{
s1str = extractGaps(jalview.util.Comparison.GapChars, string1);
s2str = extractGaps(jalview.util.Comparison.GapChars, string2);
return;
}
- // System.out.println("lookuip " + rt.freeMemory() + " "+ rt.totalMemory());
- seq1 = new int[s1str.length()];
-
- // System.out.println("seq1 " + rt.freeMemory() +" " + rt.totalMemory());
- seq2 = new int[s2str.length()];
-
- // System.out.println("seq2 " + rt.freeMemory() + " " + rt.totalMemory());
- score = new int[s1str.length()][s2str.length()];
+ score = new float[s1str.length()][s2str.length()];
- // System.out.println("score " + rt.freeMemory() + " " + rt.totalMemory());
- E = new int[s1str.length()][s2str.length()];
+ E = new float[s1str.length()][s2str.length()];
- // System.out.println("E " + rt.freeMemory() + " " + rt.totalMemory());
- F = new int[s1str.length()][s2str.length()];
+ F = new float[s1str.length()][s2str.length()];
traceback = new int[s1str.length()][s2str.length()];
- // System.out.println("F " + rt.freeMemory() + " " + rt.totalMemory());
- seq1 = stringToInt(s1str, type);
-
- // System.out.println("seq1 " + rt.freeMemory() + " " + rt.totalMemory());
- seq2 = stringToInt(s2str, type);
-
- // System.out.println("Seq2 " + rt.freeMemory() + " " + rt.totalMemory());
- // long tstart = System.currentTimeMillis();
- // calcScoreMatrix();
- // long tend = System.currentTimeMillis();
- // System.out.println("Time take to calculate score matrix = " +
- // (tend-tstart) + " ms");
- // printScoreMatrix(score);
- // System.out.println();
- // printScoreMatrix(traceback);
- // System.out.println();
- // printScoreMatrix(E);
- // System.out.println();
- // /printScoreMatrix(F);
- // System.out.println();
- // tstart = System.currentTimeMillis();
- // traceAlignment();
- // tend = System.currentTimeMillis();
- // System.out.println("Time take to traceback alignment = " + (tend-tstart)
- // + " ms");
- }
-
- private void setDefaultParams(String type)
- {
- setType(type);
+ seq1 = indexEncode(s1str);
- if (type.equals(AlignSeq.PEP))
- {
- lookup = ResidueProperties.getDefaultPeptideMatrix();
- }
- else if (type.equals(AlignSeq.DNA))
- {
- lookup = ResidueProperties.getDefaultDnaMatrix();
- }
+ seq2 = indexEncode(s2str);
}
- private void setType(String type2)
+ private void setDefaultParams(String moleculeType)
{
- this.type = type2;
- if (type.equals(AlignSeq.PEP))
- {
- intToStr = pep;
- charToInt = ResidueProperties.aaIndex;
- defInt = ResidueProperties.maxProteinIndex;
- }
- else if (type.equals(AlignSeq.DNA))
- {
- intToStr = dna;
- charToInt = ResidueProperties.nucleotideIndex;
- defInt = ResidueProperties.maxNucleotideIndex;
- }
- else
+ if (!PEP.equals(moleculeType) && !DNA.equals(moleculeType))
{
output.append("Wrong type = dna or pep only");
throw new Error(MessageManager.formatMessage(
- "error.unknown_type_dna_or_pep", new String[] { type2 }));
+ "error.unknown_type_dna_or_pep",
+ new String[] { moleculeType }));
}
+
+ type = moleculeType;
+ scoreMatrix = ScoreModels.getInstance().getDefaultModel(
+ PEP.equals(type));
}
/**
public void traceAlignment()
{
// Find the maximum score along the rhs or bottom row
- int max = -9999;
+ float max = -Float.MAX_VALUE;
for (int i = 0; i < seq1.length; i++)
{
aseq1 = new int[seq1.length + seq2.length];
aseq2 = new int[seq1.length + seq2.length];
+ StringBuilder sb1 = new StringBuilder(aseq1.length);
+ StringBuilder sb2 = new StringBuilder(aseq2.length);
+
count = (seq1.length + seq2.length) - 1;
- while ((i > 0) && (j > 0))
+ while (i > 0 && j > 0)
{
- if ((aseq1[count] != defInt) && (i >= 0))
- {
- aseq1[count] = seq1[i];
- astr1 = s1str.charAt(i) + astr1;
- }
-
- if ((aseq2[count] != defInt) && (j > 0))
- {
- aseq2[count] = seq2[j];
- astr2 = s2str.charAt(j) + astr2;
- }
+ aseq1[count] = seq1[i];
+ sb1.append(s1str.charAt(i));
+ aseq2[count] = seq2[j];
+ sb2.append(s2str.charAt(j));
trace = findTrace(i, j);
else if (trace == 1)
{
j--;
- aseq1[count] = defInt;
- astr1 = "-" + astr1.substring(1);
+ aseq1[count] = GAP_INDEX;
+ sb1.replace(sb1.length() - 1, sb1.length(), "-");
}
else if (trace == -1)
{
i--;
- aseq2[count] = defInt;
- astr2 = "-" + astr2.substring(1);
+ aseq2[count] = GAP_INDEX;
+ sb2.replace(sb2.length() - 1, sb2.length(), "-");
}
count--;
seq1start = i + 1;
seq2start = j + 1;
- if (aseq1[count] != defInt)
+ if (aseq1[count] != GAP_INDEX)
{
aseq1[count] = seq1[i];
- astr1 = s1str.charAt(i) + astr1;
+ sb1.append(s1str.charAt(i));
}
- if (aseq2[count] != defInt)
+ if (aseq2[count] != GAP_INDEX)
{
aseq2[count] = seq2[j];
- astr2 = s2str.charAt(j) + astr2;
+ sb2.append(s2str.charAt(j));
}
+
+ /*
+ * we built the character strings backwards, so now
+ * reverse them to convert to sequence strings
+ */
+ astr1 = sb1.reverse().toString();
+ astr2 = sb2.reverse().toString();
}
/**
.append(String.valueOf(s2str.length())).append(")")
.append(NEWLINE).append(NEWLINE);
+ ScoreMatrix pam250 = ScoreModels.getInstance().getPam250();
+
for (int j = 0; j < nochunks; j++)
{
// Print the first aligned sequence
output.append(NEWLINE);
output.append(new Format("%" + (maxid) + "s").form(" ")).append(" ");
- // Print out the matching chars
+ /*
+ * Print out the match symbols:
+ * | for exact match (ignoring case)
+ * . if PAM250 score is positive
+ * else a space
+ */
for (int i = 0; i < len; i++)
{
if ((i + (j * len)) < astr1.length())
{
- boolean sameChar = Comparison.isSameResidue(
- astr1.charAt(i + (j * len)), astr2.charAt(i + (j * len)),
- false);
- if (sameChar
- && !jalview.util.Comparison.isGap(astr1.charAt(i
- + (j * len))))
+ char c1 = astr1.charAt(i + (j * len));
+ char c2 = astr2.charAt(i + (j * len));
+ boolean sameChar = Comparison.isSameResidue(c1, c2, false);
+ if (sameChar && !Comparison.isGap(c1))
{
pid++;
output.append("|");
}
else if (type.equals("pep"))
{
- if (ResidueProperties.getPAM250(astr1.charAt(i + (j * len)),
- astr2.charAt(i + (j * len))) > 0)
+ if (pam250.getPairwiseScore(c1, c2) > 0)
{
output.append(".");
}
/**
* DOCUMENT ME!
*
- * @param mat
- * DOCUMENT ME!
- */
- public void printScoreMatrix(int[][] mat)
- {
- int n = seq1.length;
- int m = seq2.length;
-
- for (int i = 0; i < n; i++)
- {
- // Print the top sequence
- if (i == 0)
- {
- Format.print(System.out, "%8s", s2str.substring(0, 1));
-
- for (int jj = 1; jj < m; jj++)
- {
- Format.print(System.out, "%5s", s2str.substring(jj, jj + 1));
- }
-
- System.out.println();
- }
-
- for (int j = 0; j < m; j++)
- {
- if (j == 0)
- {
- Format.print(System.out, "%3s", s1str.substring(i, i + 1));
- }
-
- Format.print(System.out, "%3d ", mat[i][j] / 10);
- }
-
- System.out.println();
- }
- }
-
- /**
- * DOCUMENT ME!
- *
* @param i
* DOCUMENT ME!
* @param j
public int findTrace(int i, int j)
{
int t = 0;
- int max = score[i - 1][j - 1] + (lookup[seq1[i]][seq2[j]] * 10);
+ // float pairwiseScore = lookup[seq1[i]][seq2[j]];
+ float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
+ s2str.charAt(j));
+ float max = score[i - 1][j - 1] + (pairwiseScore * 10);
if (F[i][j] > max)
{
int m = seq2.length;
// top left hand element
- score[0][0] = lookup[seq1[0]][seq2[0]] * 10;
+ score[0][0] = scoreMatrix.getPairwiseScore(s1str.charAt(0),
+ s2str.charAt(0)) * 10;
E[0][0] = -gapExtend;
F[0][0] = 0;
E[0][j] = max(score[0][j - 1] - gapOpen, E[0][j - 1] - gapExtend);
F[0][j] = -gapExtend;
- score[0][j] = max(lookup[seq1[0]][seq2[j]] * 10, -gapOpen, -gapExtend);
+ float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(0),
+ s2str.charAt(j));
+ score[0][j] = max(pairwiseScore * 10, -gapOpen, -gapExtend);
traceback[0][j] = 1;
}
E[i][0] = -gapOpen;
F[i][0] = max(score[i - 1][0] - gapOpen, F[i - 1][0] - gapExtend);
- score[i][0] = max(lookup[seq1[i]][seq2[0]] * 10, E[i][0], F[i][0]);
+ float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
+ s2str.charAt(0));
+ score[i][0] = max(pairwiseScore * 10, E[i][0], F[i][0]);
traceback[i][0] = -1;
}
E[i][j] = max(score[i][j - 1] - gapOpen, E[i][j - 1] - gapExtend);
F[i][j] = max(score[i - 1][j] - gapOpen, F[i - 1][j] - gapExtend);
+ float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
+ s2str.charAt(j));
score[i][j] = max(score[i - 1][j - 1]
- + (lookup[seq1[i]][seq2[j]] * 10), E[i][j], F[i][j]);
+ + (pairwiseScore * 10), E[i][j], F[i][j]);
traceback[i][j] = findTrace(i, j);
}
}
/**
* DOCUMENT ME!
*
- * @param i1
+ * @param f1
* DOCUMENT ME!
- * @param i2
+ * @param f2
* DOCUMENT ME!
- * @param i3
+ * @param f3
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
- public int max(int i1, int i2, int i3)
+ private static float max(float f1, float f2, float f3)
{
- int max = i1;
+ float max = f1;
- if (i2 > i1)
+ if (f2 > f1)
{
- max = i2;
+ max = f2;
}
- if (i3 > max)
+ if (f3 > max)
{
- max = i3;
+ max = f3;
}
return max;
/**
* DOCUMENT ME!
*
- * @param i1
+ * @param f1
* DOCUMENT ME!
- * @param i2
+ * @param f2
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
- public int max(int i1, int i2)
+ private static float max(float f1, float f2)
{
- int max = i1;
+ float max = f1;
- if (i2 > i1)
+ if (f2 > f1)
{
- max = i2;
+ max = f2;
}
return max;
}
/**
- * DOCUMENT ME!
+ * Converts the character string to an array of integers which are the
+ * corresponding indices to the characters in the score matrix
*
* @param s
- * DOCUMENT ME!
- * @param type
- * DOCUMENT ME!
*
- * @return DOCUMENT ME!
+ * @return
*/
- public int[] stringToInt(String s, String type)
+ int[] indexEncode(String s)
{
- int[] seq1 = new int[s.length()];
+ int[] encoded = new int[s.length()];
for (int i = 0; i < s.length(); i++)
{
- // String ss = s.substring(i, i + 1).toUpperCase();
char c = s.charAt(i);
- if ('a' <= c && c <= 'z')
- {
- // TO UPPERCASE !!!
- c -= ('a' - 'A');
- }
-
- try
- {
- seq1[i] = charToInt[c]; // set accordingly from setType
- if (seq1[i] < 0 || seq1[i] > defInt) // set from setType: 23 for
- // peptides, or 4 for NA.
- {
- seq1[i] = defInt;
- }
-
- } catch (Exception e)
- {
- seq1[i] = defInt;
- }
+ encoded[i] = scoreMatrix.getMatrixIndex(c);
}
- return seq1;
+ return encoded;
}
/**
public static void displayMatrix(Graphics g, int[][] mat, int n, int m,
int psize)
{
- // TODO method dosen't seem to be referenced anywhere delete??
+ // TODO method doesn't seem to be referenced anywhere delete??
int max = -1000;
int min = 1000;
{
SequenceI bestm = null;
AlignSeq bestaseq = null;
- int bestscore = 0;
+ float bestscore = 0;
for (SequenceI msq : al.getSequences())
{
AlignSeq aseq = doGlobalNWAlignment(msq, sq, dnaOrProtein);
bestm = msq;
}
}
- System.out.println("Best Score for " + (matches.size() + 1) + " :"
- + bestscore);
+ // System.out.println("Best Score for " + (matches.size() + 1) + " :"
+ // + bestscore);
matches.add(bestm);
aligns.add(bestaseq);
al.deleteSequence(bestm);
// long start = System.currentTimeMillis();
+ SimilarityParams pidParams = new SimilarityParams(true, true, true,
+ true);
float pid;
String seqi, seqj;
for (int i = 0; i < height; i++)
seqj = ug;
}
}
- pid = Comparison.PID(seqi, seqj);
+ pid = (float) PIDModel.computePID(seqi, seqj, pidParams);
// use real sequence length rather than string length
if (lngth[j] < lngth[i])
*/
package jalview.analysis;
+import jalview.analysis.scoremodels.PIDModel;
+import jalview.analysis.scoremodels.SimilarityParams;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.datamodel.SequenceNode;
-import jalview.util.Comparison;
import jalview.util.MessageManager;
import jalview.util.QuickSort;
static boolean sortOrderAscending = true;
- static NJTree lastTree = null;
+ static TreeModel lastTree = null;
static boolean sortTreeAscending = true;
private static boolean sortLengthAscending;
/**
- * Sort by Percentage Identity w.r.t. s
+ * Sorts sequences in the alignment by Percentage Identity with the given
+ * reference sequence, sorting the highest identity to the top
*
* @param align
* AlignmentI
* @param s
* SequenceI
- * @param tosort
- * sequences from align that are to be sorted.
- */
- public static void sortByPID(AlignmentI align, SequenceI s,
- SequenceI[] tosort)
- {
- sortByPID(align, s, tosort, 0, -1);
- }
-
- /**
- * Sort by Percentage Identity w.r.t. s
- *
- * @param align
- * AlignmentI
- * @param s
- * SequenceI
- * @param tosort
- * sequences from align that are to be sorted.
- * @param start
- * start column (0 for beginning
* @param end
*/
- public static void sortByPID(AlignmentI align, SequenceI s,
- SequenceI[] tosort, int start, int end)
+ public static void sortByPID(AlignmentI align, SequenceI s)
{
int nSeq = align.getHeight();
float[] scores = new float[nSeq];
SequenceI[] seqs = new SequenceI[nSeq];
+ String refSeq = s.getSequenceAsString();
+ SimilarityParams pidParams = new SimilarityParams(true, true, true,
+ true);
for (int i = 0; i < nSeq; i++)
{
- scores[i] = Comparison.PID(align.getSequenceAt(i)
- .getSequenceAsString(), s.getSequenceAsString());
+ scores[i] = (float) PIDModel.computePID(align.getSequenceAt(i)
+ .getSequenceAsString(), refSeq, pidParams);
seqs[i] = align.getSequenceAt(i);
}
* @return DOCUMENT ME!
*/
private static List<SequenceI> getOrderByTree(AlignmentI align,
- NJTree tree)
+ TreeModel tree)
{
int nSeq = align.getHeight();
* @param tree
* tree which has
*/
- public static void sortByTree(AlignmentI align, NJTree tree)
+ public static void sortByTree(AlignmentI align, TreeModel tree)
{
List<SequenceI> tmp = getOrderByTree(align, tree);
for (int f = 0; f < sf.length; f++)
{
// filter for selection criteria
- if (
- // ignore features outwith alignment start-stop positions.
- (sf[f].end < sstart || sf[f].begin > sstop) ||
- // or ignore based on selection criteria
- (featureLabels != null && !AlignmentSorter
- .containsIgnoreCase(sf[f].type, featureLabels))
- || (groupLabels != null
- // problem here: we cannot eliminate null feature group features
- && (sf[f].getFeatureGroup() != null && !AlignmentSorter
- .containsIgnoreCase(sf[f].getFeatureGroup(),
- groupLabels))))
+ SequenceFeature feature = sf[f];
+
+ /*
+ * double-check feature overlaps columns (JAL-2544)
+ * (could avoid this with a findPositions(fromCol, toCol) method)
+ * findIndex returns base 1 column values, startCol/endCol are base 0
+ */
+ boolean noOverlap = seqs[i].findIndex(feature.getBegin()) > stop + 1
+ || seqs[i].findIndex(feature.getEnd()) < start + 1;
+ boolean skipFeatureType = featureLabels != null
+ && !AlignmentSorter.containsIgnoreCase(feature.type,
+ featureLabels);
+ boolean skipFeatureGroup = groupLabels != null
+ && (feature.getFeatureGroup() != null && !AlignmentSorter
+ .containsIgnoreCase(feature.getFeatureGroup(),
+ groupLabels));
+ if (noOverlap || skipFeatureType || skipFeatureGroup)
{
// forget about this feature
sf[f] = null;
else
{
// or, also take a look at the scores if necessary.
- if (!ignoreScore && !Float.isNaN(sf[f].getScore()))
+ if (!ignoreScore && !Float.isNaN(feature.getScore()))
{
if (seqScores[i] == 0)
{
}
seqScores[i]++;
hasScore[i] = true;
- scores[i] += sf[f].getScore(); // take the first instance of this
+ scores[i] += feature.getScore(); // take the first instance of this
// score.
}
}
--- /dev/null
+package jalview.analysis;
+
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.SequenceNode;
+import jalview.viewmodel.AlignmentViewport;
+
+/**
+ * This class implements distance calculations used in constructing a Average
+ * Distance tree (also known as UPGMA)
+ */
+public class AverageDistanceTree extends TreeBuilder
+{
+ /**
+ * Constructor
+ *
+ * @param av
+ * @param sm
+ * @param scoreParameters
+ */
+ public AverageDistanceTree(AlignmentViewport av, ScoreModelI sm,
+ SimilarityParamsI scoreParameters)
+ {
+ super(av, sm, scoreParameters);
+ }
+
+ /**
+ * Calculates and saves the distance between the combination of cluster(i) and
+ * cluster(j) and all other clusters. An average of the distances from
+ * cluster(i) and cluster(j) is calculated, weighted by the sizes of each
+ * cluster.
+ *
+ * @param i
+ * @param j
+ */
+ @Override
+ protected void findClusterDistance(int i, int j)
+ {
+ int noi = clusters.elementAt(i).cardinality();
+ int noj = clusters.elementAt(j).cardinality();
+
+ // New distances from cluster i to others
+ double[] newdist = new double[noseqs];
+
+ for (int l = 0; l < noseqs; l++)
+ {
+ if ((l != i) && (l != j))
+ {
+ newdist[l] = ((distances.getValue(i, l) * noi) + (distances
+ .getValue(j, l) * noj)) / (noi + noj);
+ }
+ else
+ {
+ newdist[l] = 0;
+ }
+ }
+
+ for (int ii = 0; ii < noseqs; ii++)
+ {
+ distances.setValue(i, ii, newdist[ii]);
+ distances.setValue(ii, i, newdist[ii]);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected double findMinDistance()
+ {
+ double min = Double.MAX_VALUE;
+
+ for (int i = 0; i < (noseqs - 1); i++)
+ {
+ for (int j = i + 1; j < noseqs; j++)
+ {
+ if (!done.get(i) && !done.get(j))
+ {
+ if (distances.getValue(i, j) < min)
+ {
+ mini = i;
+ minj = j;
+
+ min = distances.getValue(i, j);
+ }
+ }
+ }
+ }
+ return min;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void findNewDistances(SequenceNode nodei, SequenceNode nodej,
+ double dist)
+ {
+ double ih = 0;
+ double jh = 0;
+
+ SequenceNode sni = nodei;
+ SequenceNode snj = nodej;
+
+ while (sni != null)
+ {
+ ih = ih + sni.dist;
+ sni = (SequenceNode) sni.left();
+ }
+
+ while (snj != null)
+ {
+ jh = jh + snj.dist;
+ snj = (SequenceNode) snj.left();
+ }
+
+ nodei.dist = ((dist / 2) - ih);
+ nodej.dist = ((dist / 2) - jh);
+ }
+
+}
*/
package jalview.analysis;
+import jalview.analysis.scoremodels.ScoreMatrix;
+import jalview.analysis.scoremodels.ScoreModels;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.datamodel.ResidueCount;
private static final int TOUPPERCASE = 'a' - 'A';
+ private static final int GAP_INDEX = -1;
+
SequenceI[] sequences;
int start;
int end;
- Vector<int[]> seqNums; // vector of int vectors where first is sequence
- // checksum
+ /*
+ * a list whose i'th element is an array whose first entry is the checksum
+ * of the i'th sequence, followed by residues encoded to score matrix index
+ */
+ Vector<int[]> seqNums;
int maxLength = 0; // used by quality calcs
*/
Map<String, Integer>[] total;
- boolean canonicaliseAa = true; // if true then conservation calculation will
-
- // map all symbols to canonical aa numbering
- // rather than consider conservation of that
- // symbol
+ /*
+ * if true then conservation calculation will map all symbols to canonical aa
+ * numbering rather than consider conservation of that symbol
+ */
+ boolean canonicaliseAa = true;
- /** Stores calculated quality values */
private Vector<Double> quality;
- /** Stores maximum and minimum values of quality values */
- private double[] qualityRange = new double[2];
+ private double qualityMinimum;
+
+ private double qualityMaximum;
private Sequence consSequence;
private String name = "";
+ /*
+ * an array, for each column, of counts of symbols (by score matrix index)
+ */
private int[][] cons2;
+ /*
+ * gap counts for each column
+ */
+ private int[] cons2GapCounts;
+
private String[] consSymbs;
/**
}
/**
- * Translate sequence i into a numerical representation and store it in the
- * i'th position of the seqNums array.
+ * Translate sequence i into score matrix indices and store it in the i'th
+ * position of the seqNums array.
*
* @param i
+ * @param sm
*/
- private void calcSeqNum(int i)
+ private void calcSeqNum(int i, ScoreMatrix sm)
{
- String sq = null; // for dumb jbuilder not-inited exception warning
- int[] sqnum = null;
-
int sSize = sequences.length;
if ((i > -1) && (i < sSize))
{
- sq = sequences[i].getSequenceAsString();
+ String sq = sequences[i].getSequenceAsString();
if (seqNums.size() <= i)
{
seqNums.addElement(new int[sq.length() + 1]);
}
+ /*
+ * the first entry in the array is the sequence's hashcode,
+ * following entries are matrix indices of sequence characters
+ */
if (sq.hashCode() != seqNums.elementAt(i)[0])
{
int j;
maxLength = len;
}
- sqnum = new int[len + 1]; // better to always make a new array -
+ int[] sqnum = new int[len + 1]; // better to always make a new array -
// sequence can change its length
sqnum[0] = sq.hashCode();
for (j = 1; j <= len; j++)
{
- sqnum[j] = jalview.schemes.ResidueProperties.aaIndex[sq
- .charAt(j - 1)];
+ // sqnum[j] = ResidueProperties.aaIndex[sq.charAt(j - 1)];
+ char residue = sq.charAt(j - 1);
+ if (Comparison.isGap(residue))
+ {
+ sqnum[j] = GAP_INDEX;
+ }
+ else
+ {
+ sqnum[j] = sm.getMatrixIndex(residue);
+ if (sqnum[j] == -1)
+ {
+ sqnum[j] = GAP_INDEX;
+ }
+ }
}
seqNums.setElementAt(sqnum, i);
// From Alignment.java in jalview118
public void findQuality()
{
- findQuality(0, maxLength - 1);
+ findQuality(0, maxLength - 1, ScoreModels.getInstance().getBlosum62());
}
/**
* DOCUMENT ME!
+ *
+ * @param sm
*/
- private void percentIdentity2()
+ private void percentIdentity(ScoreMatrix sm)
{
seqNums = new Vector<int[]>();
- // calcSeqNum(s);
int i = 0, iSize = sequences.length;
// Do we need to calculate this again?
for (i = 0; i < iSize; i++)
{
- calcSeqNum(i);
+ calcSeqNum(i, sm);
}
if ((cons2 == null) || seqNumsChanged)
{
+ // FIXME remove magic number 24 without changing calc
+ // sm.getSize() returns 25 so doesn't quite do it...
cons2 = new int[maxLength][24];
+ cons2GapCounts = new int[maxLength];
- // Initialize the array
- for (int j = 0; j < 24; j++)
- {
- for (i = 0; i < maxLength; i++)
- {
- cons2[i][j] = 0;
- }
- }
-
- int[] sqnum;
int j = 0;
while (j < sequences.length)
{
- sqnum = seqNums.elementAt(j);
+ int[] sqnum = seqNums.elementAt(j);
for (i = 1; i < sqnum.length; i++)
{
- cons2[i - 1][sqnum[i]]++;
+ int index = sqnum[i];
+ if (index == GAP_INDEX)
+ {
+ cons2GapCounts[i - 1]++;
+ }
+ else
+ {
+ cons2[i - 1][index]++;
+ }
}
+ // TODO should this start from sqnum.length?
for (i = sqnum.length - 1; i < maxLength; i++)
{
- cons2[i][23]++; // gap count
+ cons2GapCounts[i]++;
}
-
j++;
}
-
- // unnecessary ?
-
- /*
- * for (int i=start; i <= end; i++) { int max = -1000; int maxi = -1; int
- * maxj = -1;
- *
- * for (int j=0;j<24;j++) { if (cons2[i][j] > max) { max = cons2[i][j];
- * maxi = i; maxj = j; } } }
- */
}
}
/**
- * Calculates the quality of the set of sequences
+ * Calculates the quality of the set of sequences over the given inclusive
+ * column range, using the specified substitution score matrix
*
- * @param startRes
- * Start residue
- * @param endRes
- * End residue
+ * @param startCol
+ * @param endCol
+ * @param scoreMatrix
*/
- public void findQuality(int startRes, int endRes)
+ protected void findQuality(int startCol, int endCol, ScoreMatrix scoreMatrix)
{
quality = new Vector<Double>();
- double max = -10000;
- int[][] BLOSUM62 = ResidueProperties.getBLOSUM62();
+ double max = -Double.MAX_VALUE;
+ float[][] scores = scoreMatrix.getMatrix();
- // Loop over columns // JBPNote Profiling info
- // long ts = System.currentTimeMillis();
- // long te = System.currentTimeMillis();
- percentIdentity2();
+ percentIdentity(scoreMatrix);
int size = seqNums.size();
int[] lengths = new int[size];
- double tot, bigtot, sr, tmp;
- double[] x, xx;
- int l, j, i, ii, i2, k, seqNum;
- for (l = 0; l < size; l++)
+ for (int l = 0; l < size; l++)
{
lengths[l] = seqNums.elementAt(l).length - 1;
}
- for (j = startRes; j <= endRes; j++)
+ final int symbolCount = scoreMatrix.getSize();
+
+ for (int j = startCol; j <= endCol; j++)
{
- bigtot = 0;
+ double bigtot = 0;
// First Xr = depends on column only
- x = new double[24];
+ double[] x = new double[symbolCount];
- for (ii = 0; ii < 24; ii++)
+ for (int ii = 0; ii < symbolCount; ii++)
{
x[ii] = 0;
- for (i2 = 0; i2 < 24; i2++)
+ /*
+ * todo JAL-728 currently assuming last symbol in matrix is * for gap
+ * (which we ignore as counted separately); true for BLOSUM62 but may
+ * not be once alternative matrices are supported
+ */
+ for (int i2 = 0; i2 < symbolCount - 1; i2++)
{
- x[ii] += (((double) cons2[j][i2] * BLOSUM62[ii][i2]) + 4);
+ x[ii] += (((double) cons2[j][i2] * scores[ii][i2]) + 4D);
}
+ x[ii] += 4D + cons2GapCounts[j] * scoreMatrix.getMinimumScore();
x[ii] /= size;
}
// Now calculate D for each position and sum
- for (k = 0; k < size; k++)
+ for (int k = 0; k < size; k++)
{
- tot = 0;
- xx = new double[24];
- seqNum = (j < lengths[k]) ? seqNums.elementAt(k)[j + 1] : 23; // Sequence,
- // or gap
- // at the
- // end
-
- // This is a loop over r
- for (i = 0; i < 23; i++)
- {
- sr = 0;
+ double tot = 0;
+ double[] xx = new double[symbolCount];
+ // sequence character index, or implied gap if sequence too short
+ int seqNum = (j < lengths[k]) ? seqNums.elementAt(k)[j + 1]
+ : GAP_INDEX;
- sr = (double) BLOSUM62[i][seqNum] + 4;
+ for (int i = 0; i < symbolCount - 1; i++)
+ {
+ double sr = 4D;
+ if (seqNum == GAP_INDEX)
+ {
+ sr += scoreMatrix.getMinimumScore();
+ }
+ else
+ {
+ sr += scores[i][seqNum];
+ }
- // Calculate X with another loop over residues
- // System.out.println("Xi " + i + " " + x[i] + " " + sr);
xx[i] = x[i] - sr;
tot += (xx[i] * xx[i]);
bigtot += Math.sqrt(tot);
}
- // This is the quality for one column
- if (max < bigtot)
- {
- max = bigtot;
- }
+ max = Math.max(max, bigtot);
- // bigtot = bigtot * (size-cons2[j][23])/size;
quality.addElement(new Double(bigtot));
-
- // Need to normalize by gaps
}
- double newmax = -10000;
+ double newmax = -Double.MAX_VALUE;
- for (j = startRes; j <= endRes; j++)
+ for (int j = startCol; j <= endCol; j++)
{
- tmp = quality.elementAt(j).doubleValue();
- tmp = ((max - tmp) * (size - cons2[j][23])) / size;
+ double tmp = quality.elementAt(j).doubleValue();
+ // tmp = ((max - tmp) * (size - cons2[j][23])) / size;
+ tmp = ((max - tmp) * (size - cons2GapCounts[j])) / size;
// System.out.println(tmp+ " " + j);
quality.setElementAt(new Double(tmp), j);
}
}
- // System.out.println("Quality " + s);
- qualityRange[0] = 0D;
- qualityRange[1] = newmax;
+ qualityMinimum = 0D;
+ qualityMaximum = newmax;
}
/**
if (quality2 != null)
{
- quality2.graphMax = (float) qualityRange[1];
+ quality2.graphMax = (float) qualityMaximum;
if (quality2.annotations != null
&& quality2.annotations.length < alWidth)
{
quality2.annotations = new Annotation[alWidth];
}
- qmin = (float) qualityRange[0];
- qmax = (float) qualityRange[1];
+ qmin = (float) qualityMinimum;
+ qmax = (float) qualityMaximum;
}
for (int i = istart; i < alWidth; i++)
package jalview.analysis;
import jalview.api.analysis.ScoreModelI;
-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.api.analysis.SimilarityParamsI;
import jalview.datamodel.SequenceNode;
-import jalview.io.NewickFile;
-import jalview.schemes.ResidueProperties;
-
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Vector;
+import jalview.viewmodel.AlignmentViewport;
/**
- * DOCUMENT ME!
- *
- * @author $author$
- * @version $Revision$
+ * This class implements distance calculations used in constructing a Neighbour
+ * Joining tree
*/
-public class NJTree
+public class NJTree extends TreeBuilder
{
- Vector<Cluster> cluster;
-
- SequenceI[] sequence;
-
- // SequenceData is a string representation of what the user
- // sees. The display may contain hidden columns.
- public AlignmentView seqData = null;
-
- int[] done;
-
- int noseqs;
-
- int noClus;
-
- float[][] distance;
-
- int mini;
-
- int minj;
-
- float ri;
-
- float rj;
-
- Vector<SequenceNode> groups = new Vector<SequenceNode>();
-
- SequenceNode maxdist;
-
- SequenceNode top;
-
- float maxDistValue;
-
- float maxheight;
-
- int ycount;
-
- Vector<SequenceNode> node;
-
- String type;
-
- String pwtype;
-
- Object found = null;
-
- boolean hasDistances = true; // normal case for jalview trees
-
- boolean hasBootstrap = false; // normal case for jalview trees
-
- private boolean hasRootDistance = true;
-
- /**
- * Create a new NJTree object with leaves associated with sequences in seqs,
- * and original alignment data represented by Cigar strings.
- *
- * @param seqs
- * SequenceI[]
- * @param odata
- * Cigar[]
- * @param treefile
- * NewickFile
- */
- public NJTree(SequenceI[] seqs, AlignmentView odata, NewickFile treefile)
- {
- this(seqs, treefile);
- if (odata != null)
- {
- seqData = odata;
- }
- /*
- * sequenceString = new String[odata.length]; char gapChar =
- * jalview.util.Comparison.GapChars.charAt(0); for (int i = 0; i <
- * odata.length; i++) { SequenceI oseq_aligned = odata[i].getSeq(gapChar);
- * sequenceString[i] = oseq_aligned.getSequence(); }
- */
- }
-
- /**
- * Creates a new NJTree object from a tree from an external source
- *
- * @param seqs
- * SequenceI which should be associated with leafs of treefile
- * @param treefile
- * A parsed tree
- */
- public NJTree(SequenceI[] seqs, NewickFile treefile)
- {
- this.sequence = seqs;
- top = treefile.getTree();
-
- /**
- * There is no dependent alignment to be recovered from an imported tree.
- *
- * if (sequenceString == null) { sequenceString = new String[seqs.length];
- * for (int i = 0; i < seqs.length; i++) { sequenceString[i] =
- * seqs[i].getSequence(); } }
- */
-
- hasDistances = treefile.HasDistances();
- hasBootstrap = treefile.HasBootstrap();
- hasRootDistance = treefile.HasRootDistance();
-
- maxheight = findHeight(top);
-
- SequenceIdMatcher algnIds = new SequenceIdMatcher(seqs);
-
- Vector<SequenceNode> leaves = findLeaves(top);
-
- int i = 0;
- int namesleft = seqs.length;
-
- SequenceNode j;
- SequenceI nam;
- String realnam;
- Vector<SequenceI> one2many = new Vector<SequenceI>();
- int countOne2Many = 0;
- while (i < leaves.size())
- {
- j = leaves.elementAt(i++);
- realnam = j.getName();
- nam = null;
-
- if (namesleft > -1)
- {
- nam = algnIds.findIdMatch(realnam);
- }
-
- if (nam != null)
- {
- j.setElement(nam);
- if (one2many.contains(nam))
- {
- countOne2Many++;
- // if (jalview.bin.Cache.log.isDebugEnabled())
- // jalview.bin.Cache.log.debug("One 2 many relationship for
- // "+nam.getName());
- }
- else
- {
- one2many.addElement(nam);
- namesleft--;
- }
- }
- else
- {
- j.setElement(new Sequence(realnam, "THISISAPLACEHLDER"));
- j.setPlaceholder(true);
- }
- }
- // if (jalview.bin.Cache.log.isDebugEnabled() && countOne2Many>0) {
- // jalview.bin.Cache.log.debug("There were "+countOne2Many+" alignment
- // sequence ids (out of "+one2many.size()+" unique ids) linked to two or
- // more leaves.");
- // }
- // one2many.clear();
- }
-
/**
- * Creates a new NJTree object.
+ * Constructor given a viewport, tree type and score model
*
- * @param sequence
- * DOCUMENT ME!
- * @param type
- * DOCUMENT ME!
- * @param pwtype
- * DOCUMENT ME!
- * @param start
- * DOCUMENT ME!
- * @param end
- * DOCUMENT ME!
+ * @param av
+ * the current alignment viewport
+ * @param sm
+ * a distance or similarity score model to use to compute the tree
+ * @param scoreParameters
*/
- public NJTree(SequenceI[] sequence, AlignmentView seqData, String type,
- String pwtype, ScoreModelI sm, int start, int end)
+ public NJTree(AlignmentViewport av, ScoreModelI sm,
+ SimilarityParamsI scoreParameters)
{
- this.sequence = sequence;
- this.node = new Vector<SequenceNode>();
- this.type = type;
- this.pwtype = pwtype;
- if (seqData != null)
- {
- this.seqData = seqData;
- }
- else
- {
- SeqCigar[] seqs = new SeqCigar[sequence.length];
- for (int i = 0; i < sequence.length; i++)
- {
- seqs[i] = new SeqCigar(sequence[i], start, end);
- }
- CigarArray sdata = new CigarArray(seqs);
- sdata.addOperation(CigarArray.M, end - start + 1);
- this.seqData = new AlignmentView(sdata, start);
- }
- // System.err.println("Made seqData");// dbg
- if (!(type.equals("NJ")))
- {
- type = "AV";
- }
-
- if (sm == null && !(pwtype.equals("PID")))
- {
- if (ResidueProperties.getScoreMatrix(pwtype) == null)
- {
- pwtype = "BLOSUM62";
- }
- }
-
- int i = 0;
-
- done = new int[sequence.length];
-
- while ((i < sequence.length) && (sequence[i] != null))
- {
- done[i] = 0;
- i++;
- }
-
- noseqs = i++;
-
- distance = findDistances(sm);
- // System.err.println("Made distances");// dbg
- makeLeaves();
- // System.err.println("Made leaves");// dbg
-
- noClus = cluster.size();
-
- cluster();
- // System.err.println("Made clusters");// dbg
-
+ super(av, sm, scoreParameters);
}
/**
- * Generate a string representation of the Tree
- *
- * @return Newick File with all tree data available
+ * {@inheritDoc}
*/
@Override
- public String toString()
- {
- jalview.io.NewickFile fout = new jalview.io.NewickFile(getTopNode());
-
- return fout.print(isHasBootstrap(), isHasDistances(),
- isHasRootDistance()); // output all data available for tree
- }
-
- /**
- *
- * used when the alignment associated to a tree has changed.
- *
- * @param list
- * Sequence set to be associated with tree nodes
- */
- public void UpdatePlaceHolders(List<SequenceI> list)
+ protected double findMinDistance()
{
- Vector<SequenceNode> leaves = findLeaves(top);
+ double min = Double.MAX_VALUE;
- int sz = leaves.size();
- SequenceIdMatcher seqmatcher = null;
- int i = 0;
-
- while (i < sz)
+ for (int i = 0; i < (noseqs - 1); i++)
{
- SequenceNode leaf = leaves.elementAt(i++);
-
- if (list.contains(leaf.element()))
- {
- leaf.setPlaceholder(false);
- }
- else
+ for (int j = i + 1; j < noseqs; j++)
{
- if (seqmatcher == null)
+ if (!done.get(i) && !done.get(j))
{
- // Only create this the first time we need it
- SequenceI[] seqs = new SequenceI[list.size()];
+ double tmp = distances.getValue(i, j)
+ - (findr(i, j) + findr(j, i));
- for (int j = 0; j < seqs.length; j++)
+ if (tmp < min)
{
- seqs[j] = list.get(j);
- }
-
- seqmatcher = new SequenceIdMatcher(seqs);
- }
-
- SequenceI nam = seqmatcher.findIdMatch(leaf.getName());
+ mini = i;
+ minj = j;
- if (nam != null)
- {
- if (!leaf.isPlaceholder())
- {
- // remapping the node to a new sequenceI - should remove any refs to
- // old one.
- // TODO - make many sequenceI to one leaf mappings possible!
- // (JBPNote)
- }
- leaf.setPlaceholder(false);
- leaf.setElement(nam);
- }
- else
- {
- if (!leaf.isPlaceholder())
- {
- // Construct a new placeholder sequence object for this leaf
- leaf.setElement(new Sequence(leaf.getName(),
- "THISISAPLACEHLDER"));
+ min = tmp;
}
- leaf.setPlaceholder(true);
-
- }
- }
- }
- }
-
- /**
- * rename any nodes according to their associated sequence. This will modify
- * the tree's metadata! (ie the original NewickFile or newly generated
- * BinaryTree's label data)
- */
- public void renameAssociatedNodes()
- {
- applyToNodes(new NodeTransformI()
- {
-
- @Override
- public void transform(BinaryNode nd)
- {
- Object el = nd.element();
- if (el != null && el instanceof SequenceI)
- {
- nd.setName(((SequenceI) el).getName());
}
}
- });
- }
-
- /**
- * DOCUMENT ME!
- */
- public void cluster()
- {
- while (noClus > 2)
- {
- if (type.equals("NJ"))
- {
- findMinNJDistance();
- }
- else
- {
- findMinDistance();
- }
-
- Cluster c = joinClusters(mini, minj);
-
- done[minj] = 1;
-
- cluster.setElementAt(null, minj);
- cluster.setElementAt(c, mini);
-
- noClus--;
- }
-
- boolean onefound = false;
-
- int one = -1;
- int two = -1;
-
- for (int i = 0; i < noseqs; i++)
- {
- if (done[i] != 1)
- {
- if (onefound == false)
- {
- two = i;
- onefound = true;
- }
- else
- {
- one = i;
- }
- }
- }
-
- joinClusters(one, two);
- top = (node.elementAt(one));
-
- reCount(top);
- findHeight(top);
- findMaxDist(top);
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param i
- * DOCUMENT ME!
- * @param j
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public Cluster joinClusters(int i, int j)
- {
- float dist = distance[i][j];
-
- int noi = cluster.elementAt(i).value.length;
- int noj = cluster.elementAt(j).value.length;
-
- int[] value = new int[noi + noj];
-
- for (int ii = 0; ii < noi; ii++)
- {
- value[ii] = cluster.elementAt(i).value[ii];
- }
-
- for (int ii = noi; ii < (noi + noj); ii++)
- {
- value[ii] = cluster.elementAt(j).value[ii - noi];
- }
-
- Cluster c = new Cluster(value);
-
- ri = findr(i, j);
- rj = findr(j, i);
-
- if (type.equals("NJ"))
- {
- findClusterNJDistance(i, j);
- }
- else
- {
- findClusterDistance(i, j);
- }
-
- SequenceNode sn = new SequenceNode();
-
- sn.setLeft((node.elementAt(i)));
- sn.setRight((node.elementAt(j)));
-
- SequenceNode tmpi = (node.elementAt(i));
- SequenceNode tmpj = (node.elementAt(j));
-
- if (type.equals("NJ"))
- {
- findNewNJDistances(tmpi, tmpj, dist);
- }
- else
- {
- findNewDistances(tmpi, tmpj, dist);
- }
-
- tmpi.setParent(sn);
- tmpj.setParent(sn);
-
- node.setElementAt(sn, i);
-
- return c;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param tmpi
- * DOCUMENT ME!
- * @param tmpj
- * DOCUMENT ME!
- * @param dist
- * DOCUMENT ME!
- */
- public void findNewNJDistances(SequenceNode tmpi, SequenceNode tmpj,
- float dist)
- {
-
- tmpi.dist = ((dist + ri) - rj) / 2;
- tmpj.dist = (dist - tmpi.dist);
-
- if (tmpi.dist < 0)
- {
- tmpi.dist = 0;
- }
-
- if (tmpj.dist < 0)
- {
- tmpj.dist = 0;
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param tmpi
- * DOCUMENT ME!
- * @param tmpj
- * DOCUMENT ME!
- * @param dist
- * DOCUMENT ME!
- */
- public void findNewDistances(SequenceNode tmpi, SequenceNode tmpj,
- float dist)
- {
- float ih = 0;
- float jh = 0;
-
- SequenceNode sni = tmpi;
- SequenceNode snj = tmpj;
-
- while (sni != null)
- {
- ih = ih + sni.dist;
- sni = (SequenceNode) sni.left();
- }
-
- while (snj != null)
- {
- jh = jh + snj.dist;
- snj = (SequenceNode) snj.left();
}
- tmpi.dist = ((dist / 2) - ih);
- tmpj.dist = ((dist / 2) - jh);
+ return min;
}
/**
- * DOCUMENT ME!
- *
- * @param i
- * DOCUMENT ME!
- * @param j
- * DOCUMENT ME!
+ * {@inheritDoc}
*/
- public void findClusterDistance(int i, int j)
+ @Override
+ protected void findNewDistances(SequenceNode nodei, SequenceNode nodej,
+ double dist)
{
- int noi = cluster.elementAt(i).value.length;
- int noj = cluster.elementAt(j).value.length;
+ nodei.dist = ((dist + ri) - rj) / 2;
+ nodej.dist = (dist - nodei.dist);
- // New distances from cluster to others
- float[] newdist = new float[noseqs];
-
- for (int l = 0; l < noseqs; l++)
+ if (nodei.dist < 0)
{
- if ((l != i) && (l != j))
- {
- newdist[l] = ((distance[i][l] * noi) + (distance[j][l] * noj))
- / (noi + noj);
- }
- else
- {
- newdist[l] = 0;
- }
+ nodei.dist = 0;
}
- for (int ii = 0; ii < noseqs; ii++)
+ if (nodej.dist < 0)
{
- distance[i][ii] = newdist[ii];
- distance[ii][i] = newdist[ii];
+ nodej.dist = 0;
}
}
/**
- * DOCUMENT ME!
+ * Calculates and saves the distance between the combination of cluster(i) and
+ * cluster(j) and all other clusters. The new distance to cluster k is
+ * calculated as the average of the distances from i to k and from j to k,
+ * less half the distance from i to j.
*
* @param i
- * DOCUMENT ME!
* @param j
- * DOCUMENT ME!
*/
- public void findClusterNJDistance(int i, int j)
+ @Override
+ protected
+ void findClusterDistance(int i, int j)
{
-
- // New distances from cluster to others
- float[] newdist = new float[noseqs];
-
+ // New distances from cluster i to others
+ double[] newdist = new double[noseqs];
+
+ double ijDistance = distances.getValue(i, j);
for (int l = 0; l < noseqs; l++)
{
if ((l != i) && (l != j))
{
- newdist[l] = ((distance[i][l] + distance[j][l]) - distance[i][j]) / 2;
+ newdist[l] = (distances.getValue(i, l) + distances.getValue(j, l) - ijDistance) / 2;
}
else
{
newdist[l] = 0;
}
}
-
+
for (int ii = 0; ii < noseqs; ii++)
{
- distance[i][ii] = newdist[ii];
- distance[ii][i] = newdist[ii];
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param i
- * DOCUMENT ME!
- * @param j
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public float findr(int i, int j)
- {
- float tmp = 1;
-
- for (int k = 0; k < noseqs; k++)
- {
- if ((k != i) && (k != j) && (done[k] != 1))
- {
- tmp = tmp + distance[i][k];
- }
- }
-
- if (noClus > 2)
- {
- tmp = tmp / (noClus - 2);
+ distances.setValue(i, ii, newdist[ii]);
+ distances.setValue(ii, i, newdist[ii]);
}
-
- return tmp;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public float findMinNJDistance()
- {
- float min = 100000;
-
- for (int i = 0; i < (noseqs - 1); i++)
- {
- for (int j = i + 1; j < noseqs; j++)
- {
- if ((done[i] != 1) && (done[j] != 1))
- {
- float tmp = distance[i][j] - (findr(i, j) + findr(j, i));
-
- if (tmp < min)
- {
- mini = i;
- minj = j;
-
- min = tmp;
- }
- }
- }
- }
-
- return min;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public float findMinDistance()
- {
- float min = 100000;
-
- for (int i = 0; i < (noseqs - 1); i++)
- {
- for (int j = i + 1; j < noseqs; j++)
- {
- if ((done[i] != 1) && (done[j] != 1))
- {
- if (distance[i][j] < min)
- {
- mini = i;
- minj = j;
-
- min = distance[i][j];
- }
- }
- }
- }
-
- return min;
- }
-
- /**
- * Calculate a distance matrix given the sequence input data and score model
- *
- * @return similarity matrix used to compute tree
- */
- public float[][] findDistances(ScoreModelI _pwmatrix)
- {
-
- float[][] dist = new float[noseqs][noseqs];
- if (_pwmatrix == null)
- {
- // Resolve substitution model
- _pwmatrix = ResidueProperties.getScoreModel(pwtype);
- if (_pwmatrix == null)
- {
- _pwmatrix = ResidueProperties.getScoreMatrix("BLOSUM62");
- }
- }
- dist = _pwmatrix.findDistances(seqData);
- return dist;
-
- }
-
- /**
- * DOCUMENT ME!
- */
- public void makeLeaves()
- {
- cluster = new Vector<Cluster>();
-
- for (int i = 0; i < noseqs; i++)
- {
- SequenceNode sn = new SequenceNode();
-
- sn.setElement(sequence[i]);
- sn.setName(sequence[i].getName());
- node.addElement(sn);
-
- int[] value = new int[1];
- value[0] = i;
-
- Cluster c = new Cluster(value);
- cluster.addElement(c);
- }
- }
-
- /**
- * Search for leaf nodes below (or at) the given node
- *
- * @param nd
- * root node to search from
- *
- * @return
- */
- public Vector<SequenceNode> findLeaves(SequenceNode nd)
- {
- Vector<SequenceNode> leaves = new Vector<SequenceNode>();
- findLeaves(nd, leaves);
- return leaves;
- }
-
- /**
- * Search for leaf nodes.
- *
- * @param nd
- * root node to search from
- * @param leaves
- * Vector of leaves to add leaf node objects too.
- *
- * @return Vector of leaf nodes on binary tree
- */
- Vector<SequenceNode> findLeaves(SequenceNode nd,
- Vector<SequenceNode> leaves)
- {
- if (nd == null)
- {
- return leaves;
- }
-
- if ((nd.left() == null) && (nd.right() == null)) // Interior node
- // detection
- {
- leaves.addElement(nd);
-
- return leaves;
- }
- else
- {
- /*
- * TODO: Identify internal nodes... if (node.isSequenceLabel()) {
- * leaves.addElement(node); }
- */
- findLeaves((SequenceNode) nd.left(), leaves);
- findLeaves((SequenceNode) nd.right(), leaves);
- }
-
- return leaves;
- }
-
- /**
- * Find the leaf node with a particular ycount
- *
- * @param nd
- * initial point on tree to search from
- * @param count
- * value to search for
- *
- * @return null or the node with ycound=count
- */
- public Object findLeaf(SequenceNode nd, int count)
- {
- found = _findLeaf(nd, count);
-
- return found;
- }
-
- /*
- * #see findLeaf(SequenceNode node, count)
- */
- public Object _findLeaf(SequenceNode nd, int count)
- {
- if (nd == null)
- {
- return null;
- }
-
- if (nd.ycount == count)
- {
- found = nd.element();
-
- return found;
- }
- else
- {
- _findLeaf((SequenceNode) nd.left(), count);
- _findLeaf((SequenceNode) nd.right(), count);
- }
-
- return found;
- }
-
- /**
- * printNode is mainly for debugging purposes.
- *
- * @param nd
- * SequenceNode
- */
- public void printNode(SequenceNode nd)
- {
- if (nd == null)
- {
- return;
- }
-
- if ((nd.left() == null) && (nd.right() == null))
- {
- System.out.println("Leaf = " + ((SequenceI) nd.element()).getName());
- System.out.println("Dist " + nd.dist);
- System.out.println("Boot " + nd.getBootstrap());
- }
- else
- {
- System.out.println("Dist " + nd.dist);
- printNode((SequenceNode) nd.left());
- printNode((SequenceNode) nd.right());
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param nd
- * DOCUMENT ME!
- */
- public void findMaxDist(SequenceNode nd)
- {
- if (nd == null)
- {
- return;
- }
-
- if ((nd.left() == null) && (nd.right() == null))
- {
- float dist = nd.dist;
-
- if (dist > maxDistValue)
- {
- maxdist = nd;
- maxDistValue = dist;
- }
- }
- else
- {
- findMaxDist((SequenceNode) nd.left());
- findMaxDist((SequenceNode) nd.right());
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public Vector<SequenceNode> getGroups()
- {
- return groups;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public float getMaxHeight()
- {
- return maxheight;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param nd
- * DOCUMENT ME!
- * @param threshold
- * DOCUMENT ME!
- */
- public void groupNodes(SequenceNode nd, float threshold)
- {
- if (nd == null)
- {
- return;
- }
-
- if ((nd.height / maxheight) > threshold)
- {
- groups.addElement(nd);
- }
- else
- {
- groupNodes((SequenceNode) nd.left(), threshold);
- groupNodes((SequenceNode) nd.right(), threshold);
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param nd
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public float findHeight(SequenceNode nd)
- {
- if (nd == null)
- {
- return maxheight;
- }
-
- if ((nd.left() == null) && (nd.right() == null))
- {
- nd.height = ((SequenceNode) nd.parent()).height + nd.dist;
-
- if (nd.height > maxheight)
- {
- return nd.height;
- }
- else
- {
- return maxheight;
- }
- }
- else
- {
- if (nd.parent() != null)
- {
- nd.height = ((SequenceNode) nd.parent()).height + nd.dist;
- }
- else
- {
- maxheight = 0;
- nd.height = (float) 0.0;
- }
-
- maxheight = findHeight((SequenceNode) (nd.left()));
- maxheight = findHeight((SequenceNode) (nd.right()));
- }
-
- return maxheight;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public SequenceNode reRoot()
- {
- if (maxdist != null)
- {
- ycount = 0;
-
- float tmpdist = maxdist.dist;
-
- // New top
- SequenceNode sn = new SequenceNode();
- sn.setParent(null);
-
- // New right hand of top
- SequenceNode snr = (SequenceNode) maxdist.parent();
- changeDirection(snr, maxdist);
- System.out.println("Printing reversed tree");
- printN(snr);
- snr.dist = tmpdist / 2;
- maxdist.dist = tmpdist / 2;
-
- snr.setParent(sn);
- maxdist.setParent(sn);
-
- sn.setRight(snr);
- sn.setLeft(maxdist);
-
- top = sn;
-
- ycount = 0;
- reCount(top);
- findHeight(top);
- }
-
- return top;
- }
-
- /**
- *
- * @return true if original sequence data can be recovered
- */
- public boolean hasOriginalSequenceData()
- {
- return seqData != null;
- }
-
- /**
- * Returns original alignment data used for calculation - or null where not
- * available.
- *
- * @return null or cut'n'pasteable alignment
- */
- public String printOriginalSequenceData(char gapChar)
- {
- if (seqData == null)
- {
- return null;
- }
-
- StringBuffer sb = new StringBuffer();
- String[] seqdatas = seqData.getSequenceStrings(gapChar);
- for (int i = 0; i < seqdatas.length; i++)
- {
- sb.append(new jalview.util.Format("%-" + 15 + "s").form(sequence[i]
- .getName()));
- sb.append(" " + seqdatas[i] + "\n");
- }
- return sb.toString();
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param nd
- * DOCUMENT ME!
- */
- public void printN(SequenceNode nd)
- {
- if (nd == null)
- {
- return;
- }
-
- if ((nd.left() != null) && (nd.right() != null))
- {
- printN((SequenceNode) nd.left());
- printN((SequenceNode) nd.right());
- }
- else
- {
- System.out.println(" name = " + ((SequenceI) nd.element()).getName());
- }
-
- System.out.println(" dist = " + nd.dist + " " + nd.count + " "
- + nd.height);
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param nd
- * DOCUMENT ME!
- */
- public void reCount(SequenceNode nd)
- {
- ycount = 0;
- _lycount = 0;
- // _lylimit = this.node.size();
- _reCount(nd);
- }
-
- private long _lycount = 0, _lylimit = 0;
-
- /**
- * DOCUMENT ME!
- *
- * @param nd
- * DOCUMENT ME!
- */
- public void _reCount(SequenceNode nd)
- {
- // if (_lycount<_lylimit)
- // {
- // System.err.println("Warning: depth of _recount greater than number of nodes.");
- // }
- if (nd == null)
- {
- return;
- }
- _lycount++;
-
- if ((nd.left() != null) && (nd.right() != null))
- {
-
- _reCount((SequenceNode) nd.left());
- _reCount((SequenceNode) nd.right());
-
- SequenceNode l = (SequenceNode) nd.left();
- SequenceNode r = (SequenceNode) nd.right();
-
- nd.count = l.count + r.count;
- nd.ycount = (l.ycount + r.ycount) / 2;
- }
- else
- {
- nd.count = 1;
- nd.ycount = ycount++;
- }
- _lycount--;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param nd
- * DOCUMENT ME!
- */
- public void swapNodes(SequenceNode nd)
- {
- if (nd == null)
- {
- return;
- }
-
- SequenceNode tmp = (SequenceNode) nd.left();
-
- nd.setLeft(nd.right());
- nd.setRight(tmp);
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param nd
- * DOCUMENT ME!
- * @param dir
- * DOCUMENT ME!
- */
- public void changeDirection(SequenceNode nd, SequenceNode dir)
- {
- if (nd == null)
- {
- return;
- }
-
- if (nd.parent() != top)
- {
- changeDirection((SequenceNode) nd.parent(), nd);
-
- SequenceNode tmp = (SequenceNode) nd.parent();
-
- if (dir == nd.left())
- {
- nd.setParent(dir);
- nd.setLeft(tmp);
- }
- else if (dir == nd.right())
- {
- nd.setParent(dir);
- nd.setRight(tmp);
- }
- }
- else
- {
- if (dir == nd.left())
- {
- nd.setParent(nd.left());
-
- if (top.left() == nd)
- {
- nd.setRight(top.right());
- }
- else
- {
- nd.setRight(top.left());
- }
- }
- else
- {
- nd.setParent(nd.right());
-
- if (top.left() == nd)
- {
- nd.setLeft(top.right());
- }
- else
- {
- nd.setLeft(top.left());
- }
- }
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public SequenceNode getMaxDist()
- {
- return maxdist;
- }
-
- /**
- * DOCUMENT ME!
- *
- * @return DOCUMENT ME!
- */
- public SequenceNode getTopNode()
- {
- return top;
- }
-
- /**
- *
- * @return true if tree has real distances
- */
- public boolean isHasDistances()
- {
- return hasDistances;
- }
-
- /**
- *
- * @return true if tree has real bootstrap values
- */
- public boolean isHasBootstrap()
- {
- return hasBootstrap;
- }
-
- public boolean isHasRootDistance()
- {
- return hasRootDistance;
- }
-
- /**
- * apply the given transform to all the nodes in the tree.
- *
- * @param nodeTransformI
- */
- public void applyToNodes(NodeTransformI nodeTransformI)
- {
- for (Enumeration<SequenceNode> nodes = node.elements(); nodes
- .hasMoreElements(); nodeTransformI.transform(nodes
- .nextElement()))
- {
- ;
- }
- }
-}
-
-/**
- * DOCUMENT ME!
- *
- * @author $author$
- * @version $Revision$
- */
-class Cluster
-{
- int[] value;
-
- /**
- * Creates a new Cluster object.
- *
- * @param value
- * DOCUMENT ME!
- */
- public Cluster(int[] value)
- {
- this.value = value;
}
}
*/
package jalview.analysis;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.AlignmentView;
import jalview.math.MatrixI;
-import jalview.schemes.ResidueProperties;
-import jalview.schemes.ScoreMatrix;
import java.io.PrintStream;
*/
public class PCA implements Runnable
{
- boolean jvCalcMode = true;
-
MatrixI symm;
double[] eigenvalue;
StringBuilder details = new StringBuilder(1024);
- private String[] seqs;
-
- private ScoreMatrix scoreMatrix;
+ final private AlignmentView seqs;
- /**
- * Creates a new PCA object. By default, uses blosum62 matrix to generate
- * sequence similarity matrices
- *
- * @param s
- * Set of amino acid sequences to perform PCA on
- */
- public PCA(String[] s)
- {
- this(s, false);
- }
-
- /**
- * Creates a new PCA object. By default, uses blosum62 matrix to generate
- * sequence similarity matrices
- *
- * @param s
- * Set of sequences to perform PCA on
- * @param nucleotides
- * if true, uses standard DNA/RNA matrix for sequence similarity
- * calculation.
- */
- public PCA(String[] s, boolean nucleotides)
- {
- this(s, nucleotides, null);
- }
+ private ScoreModelI scoreModel;
+
+ private SimilarityParamsI similarityParams;
- public PCA(String[] s, boolean nucleotides, String s_m)
+ public PCA(AlignmentView s, ScoreModelI sm, SimilarityParamsI options)
{
this.seqs = s;
-
- scoreMatrix = null;
- String sm = s_m;
- if (sm != null)
- {
- scoreMatrix = ResidueProperties.getScoreMatrix(sm);
- }
- if (scoreMatrix == null)
- {
- // either we were given a non-existent score matrix or a scoremodel that
- // isn't based on a pairwise symbol score matrix
- scoreMatrix = ResidueProperties
- .getScoreMatrix(sm = (nucleotides ? "DNA" : "BLOSUM62"));
- }
- details.append("PCA calculation using " + sm
+ this.similarityParams = options;
+ this.scoreModel = sm;
+
+ details.append("PCA calculation using " + sm.getName()
+ " sequence similarity matrix\n========\n\n");
}
// long now = System.currentTimeMillis();
try
{
- details.append("PCA Calculation Mode is "
- + (jvCalcMode ? "Jalview variant" : "Original SeqSpace")
- + "\n");
-
- eigenvector = scoreMatrix.computePairwiseScores(seqs);
+ eigenvector = scoreModel.findSimilarities(seqs, similarityParams);
details.append(" --- OrigT * Orig ---- \n");
eigenvector.print(ps, "%8.2f");
// + (System.currentTimeMillis() - now) + "ms"));
}
- public void setJvCalcMode(boolean calcMode)
- {
- this.jvCalcMode = calcMode;
- }
-
/**
* Answers the N dimensions of the NxN PCA matrix. This is the number of
* sequences involved in the pairwise score calculation.
public int getHeight()
{
// TODO can any of seqs[] be null?
- return seqs.length;
+ return seqs.getSequences().length;
}
}
--- /dev/null
+package jalview.analysis;
+
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.CigarArray;
+import jalview.datamodel.SeqCigar;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequenceNode;
+import jalview.math.MatrixI;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.util.BitSet;
+import java.util.Vector;
+
+public abstract class TreeBuilder
+{
+ public static final String AVERAGE_DISTANCE = "AV";
+
+ public static final String NEIGHBOUR_JOINING = "NJ";
+
+ protected Vector<BitSet> clusters;
+
+ protected SequenceI[] sequences;
+
+ public AlignmentView seqData;
+
+ protected BitSet done;
+
+ protected int noseqs;
+
+ int noClus;
+
+ protected MatrixI distances;
+
+ protected int mini;
+
+ protected int minj;
+
+ protected double ri;
+
+ protected double rj;
+
+ SequenceNode maxdist;
+
+ SequenceNode top;
+
+ double maxDistValue;
+
+ double maxheight;
+
+ int ycount;
+
+ Vector<SequenceNode> node;
+
+ private AlignmentView seqStrings;
+
+ /**
+ * Constructor
+ *
+ * @param av
+ * @param sm
+ * @param scoreParameters
+ */
+ public TreeBuilder(AlignmentViewport av, ScoreModelI sm,
+ SimilarityParamsI scoreParameters)
+ {
+ int start, end;
+ boolean selview = av.getSelectionGroup() != null
+ && av.getSelectionGroup().getSize() > 1;
+ seqStrings = av.getAlignmentView(selview);
+ if (!selview)
+ {
+ start = 0;
+ end = av.getAlignment().getWidth();
+ this.sequences = av.getAlignment().getSequencesArray();
+ }
+ else
+ {
+ start = av.getSelectionGroup().getStartRes();
+ end = av.getSelectionGroup().getEndRes() + 1;
+ this.sequences = av.getSelectionGroup().getSequencesInOrder(
+ av.getAlignment());
+ }
+
+ init(seqStrings, start, end);
+
+ computeTree(sm, scoreParameters);
+ }
+
+ public SequenceI[] getSequences()
+ {
+ return sequences;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param nd
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ double findHeight(SequenceNode nd)
+ {
+ if (nd == null)
+ {
+ return maxheight;
+ }
+
+ if ((nd.left() == null) && (nd.right() == null))
+ {
+ nd.height = ((SequenceNode) nd.parent()).height + nd.dist;
+
+ if (nd.height > maxheight)
+ {
+ return nd.height;
+ }
+ else
+ {
+ return maxheight;
+ }
+ }
+ else
+ {
+ if (nd.parent() != null)
+ {
+ nd.height = ((SequenceNode) nd.parent()).height + nd.dist;
+ }
+ else
+ {
+ maxheight = 0;
+ nd.height = (float) 0.0;
+ }
+
+ maxheight = findHeight((SequenceNode) (nd.left()));
+ maxheight = findHeight((SequenceNode) (nd.right()));
+ }
+
+ return maxheight;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param nd
+ * DOCUMENT ME!
+ */
+ void reCount(SequenceNode nd)
+ {
+ ycount = 0;
+ // _lycount = 0;
+ // _lylimit = this.node.size();
+ _reCount(nd);
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param nd
+ * DOCUMENT ME!
+ */
+ void _reCount(SequenceNode nd)
+ {
+ // if (_lycount<_lylimit)
+ // {
+ // System.err.println("Warning: depth of _recount greater than number of nodes.");
+ // }
+ if (nd == null)
+ {
+ return;
+ }
+ // _lycount++;
+
+ if ((nd.left() != null) && (nd.right() != null))
+ {
+
+ _reCount((SequenceNode) nd.left());
+ _reCount((SequenceNode) nd.right());
+
+ SequenceNode l = (SequenceNode) nd.left();
+ SequenceNode r = (SequenceNode) nd.right();
+
+ nd.count = l.count + r.count;
+ nd.ycount = (l.ycount + r.ycount) / 2;
+ }
+ else
+ {
+ nd.count = 1;
+ nd.ycount = ycount++;
+ }
+ // _lycount--;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ public SequenceNode getTopNode()
+ {
+ return top;
+ }
+
+ /**
+ *
+ * @return true if tree has real distances
+ */
+ public boolean hasDistances()
+ {
+ return true;
+ }
+
+ /**
+ *
+ * @return true if tree has real bootstrap values
+ */
+ public boolean hasBootstrap()
+ {
+ return false;
+ }
+
+ public boolean hasRootDistance()
+ {
+ return true;
+ }
+
+ /**
+ * Form clusters by grouping sub-clusters, starting from one sequence per
+ * cluster, and finishing when only two clusters remain
+ */
+ void cluster()
+ {
+ while (noClus > 2)
+ {
+ findMinDistance();
+
+ joinClusters(mini, minj);
+
+ noClus--;
+ }
+
+ int rightChild = done.nextClearBit(0);
+ int leftChild = done.nextClearBit(rightChild + 1);
+
+ joinClusters(leftChild, rightChild);
+ top = (node.elementAt(leftChild));
+
+ reCount(top);
+ findHeight(top);
+ findMaxDist(top);
+ }
+
+ /**
+ * Returns the minimum distance between two clusters, and also sets the
+ * indices of the clusters in fields mini and minj
+ *
+ * @return
+ */
+ protected abstract double findMinDistance();
+
+ /**
+ * Calculates the tree using the given score model and parameters, and the
+ * configured tree type
+ * <p>
+ * If the score model computes pairwise distance scores, then these are used
+ * directly to derive the tree
+ * <p>
+ * If the score model computes similarity scores, then the range of the scores
+ * is reversed to give a distance measure, and this is used to derive the tree
+ *
+ * @param sm
+ * @param scoreOptions
+ */
+ protected void computeTree(ScoreModelI sm, SimilarityParamsI scoreOptions)
+ {
+ distances = sm.findDistances(seqData, scoreOptions);
+
+ makeLeaves();
+
+ noClus = clusters.size();
+
+ cluster();
+ }
+
+ /**
+ * Finds the node, at or below the given node, with the maximum distance, and
+ * saves the node and the distance value
+ *
+ * @param nd
+ */
+ void findMaxDist(SequenceNode nd)
+ {
+ if (nd == null)
+ {
+ return;
+ }
+
+ if ((nd.left() == null) && (nd.right() == null))
+ {
+ double dist = nd.dist;
+
+ if (dist > maxDistValue)
+ {
+ maxdist = nd;
+ maxDistValue = dist;
+ }
+ }
+ else
+ {
+ findMaxDist((SequenceNode) nd.left());
+ findMaxDist((SequenceNode) nd.right());
+ }
+ }
+
+ /**
+ * Calculates and returns r, whatever that is
+ *
+ * @param i
+ * @param j
+ *
+ * @return
+ */
+ protected double findr(int i, int j)
+ {
+ double tmp = 1;
+
+ for (int k = 0; k < noseqs; k++)
+ {
+ if ((k != i) && (k != j) && (!done.get(k)))
+ {
+ tmp = tmp + distances.getValue(i, k);
+ }
+ }
+
+ if (noClus > 2)
+ {
+ tmp = tmp / (noClus - 2);
+ }
+
+ return tmp;
+ }
+
+ protected void init(AlignmentView seqView, int start, int end)
+ {
+ this.node = new Vector<SequenceNode>();
+ if (seqView != null)
+ {
+ this.seqData = seqView;
+ }
+ else
+ {
+ SeqCigar[] seqs = new SeqCigar[sequences.length];
+ for (int i = 0; i < sequences.length; i++)
+ {
+ seqs[i] = new SeqCigar(sequences[i], start, end);
+ }
+ CigarArray sdata = new CigarArray(seqs);
+ sdata.addOperation(CigarArray.M, end - start + 1);
+ this.seqData = new AlignmentView(sdata, start);
+ }
+
+ /*
+ * count the non-null sequences
+ */
+ noseqs = 0;
+
+ done = new BitSet();
+
+ for (SequenceI seq : sequences)
+ {
+ if (seq != null)
+ {
+ noseqs++;
+ }
+ }
+ }
+
+ /**
+ * Merges cluster(j) to cluster(i) and recalculates cluster and node distances
+ *
+ * @param i
+ * @param j
+ */
+ void joinClusters(final int i, final int j)
+ {
+ double dist = distances.getValue(i, j);
+
+ ri = findr(i, j);
+ rj = findr(j, i);
+
+ findClusterDistance(i, j);
+
+ SequenceNode sn = new SequenceNode();
+
+ sn.setLeft((node.elementAt(i)));
+ sn.setRight((node.elementAt(j)));
+
+ SequenceNode tmpi = (node.elementAt(i));
+ SequenceNode tmpj = (node.elementAt(j));
+
+ findNewDistances(tmpi, tmpj, dist);
+
+ tmpi.setParent(sn);
+ tmpj.setParent(sn);
+
+ node.setElementAt(sn, i);
+
+ /*
+ * move the members of cluster(j) to cluster(i)
+ * and mark cluster j as out of the game
+ */
+ clusters.get(i).or(clusters.get(j));
+ clusters.get(j).clear();
+ done.set(j);
+ }
+
+ /*
+ * Computes and stores new distances for nodei and nodej, given the previous
+ * distance between them
+ */
+ protected abstract void findNewDistances(SequenceNode nodei,
+ SequenceNode nodej, double previousDistance);
+
+ /**
+ * Calculates and saves the distance between the combination of cluster(i) and
+ * cluster(j) and all other clusters. The form of the calculation depends on
+ * the tree clustering method being used.
+ *
+ * @param i
+ * @param j
+ */
+ protected abstract void findClusterDistance(int i, int j);
+
+ /**
+ * Start by making a cluster for each individual sequence
+ */
+ void makeLeaves()
+ {
+ clusters = new Vector<BitSet>();
+
+ for (int i = 0; i < noseqs; i++)
+ {
+ SequenceNode sn = new SequenceNode();
+
+ sn.setElement(sequences[i]);
+ sn.setName(sequences[i].getName());
+ node.addElement(sn);
+ BitSet bs = new BitSet();
+ bs.set(i);
+ clusters.addElement(bs);
+ }
+ }
+
+ public AlignmentView getOriginalData()
+ {
+ return seqStrings;
+ }
+
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.analysis;
+
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.BinaryNode;
+import jalview.datamodel.NodeTransformI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequenceNode;
+import jalview.io.NewickFile;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * A model of a tree, either computed by Jalview or loaded from a file or other
+ * resource or service
+ */
+public class TreeModel
+{
+
+ SequenceI[] sequences;
+
+ /*
+ * SequenceData is a string representation of what the user
+ * sees. The display may contain hidden columns.
+ */
+ private AlignmentView seqData;
+
+ int noseqs;
+
+ SequenceNode top;
+
+ double maxDistValue;
+
+ double maxheight;
+
+ int ycount;
+
+ Vector<SequenceNode> node;
+
+ boolean hasDistances = true; // normal case for jalview trees
+
+ boolean hasBootstrap = false; // normal case for jalview trees
+
+ private boolean hasRootDistance = true;
+
+ /**
+ * Create a new TreeModel object with leaves associated with sequences in
+ * seqs, and (optionally) original alignment data represented by Cigar strings
+ *
+ * @param seqs
+ * SequenceI[]
+ * @param odata
+ * Cigar[]
+ * @param treefile
+ * NewickFile
+ */
+ public TreeModel(SequenceI[] seqs, AlignmentView odata, NewickFile treefile)
+ {
+ this(seqs, treefile.getTree(), treefile.HasDistances(), treefile
+ .HasBootstrap(), treefile.HasRootDistance());
+ seqData = odata;
+
+ associateLeavesToSequences(seqs);
+ }
+
+ /**
+ * Constructor given a calculated tree
+ *
+ * @param tree
+ */
+ public TreeModel(TreeBuilder tree)
+ {
+ this(tree.getSequences(), tree.getTopNode(), tree.hasDistances(), tree
+ .hasBootstrap(), tree.hasRootDistance());
+ seqData = tree.getOriginalData();
+ }
+
+ /**
+ * Constructor given sequences, root node and tree property flags
+ *
+ * @param seqs
+ * @param root
+ * @param hasDist
+ * @param hasBoot
+ * @param hasRootDist
+ */
+ public TreeModel(SequenceI[] seqs, SequenceNode root, boolean hasDist,
+ boolean hasBoot, boolean hasRootDist)
+ {
+ this.sequences = seqs;
+ top = root;
+
+ hasDistances = hasDist;
+ hasBootstrap = hasBoot;
+ hasRootDistance = hasRootDist;
+
+ maxheight = findHeight(top);
+ }
+
+ /**
+ * @param seqs
+ */
+ public void associateLeavesToSequences(SequenceI[] seqs)
+ {
+ SequenceIdMatcher algnIds = new SequenceIdMatcher(seqs);
+
+ Vector<SequenceNode> leaves = findLeaves(top);
+
+ int i = 0;
+ int namesleft = seqs.length;
+
+ SequenceNode j;
+ SequenceI nam;
+ String realnam;
+ Vector<SequenceI> one2many = new Vector<SequenceI>();
+ // int countOne2Many = 0;
+ while (i < leaves.size())
+ {
+ j = leaves.elementAt(i++);
+ realnam = j.getName();
+ nam = null;
+
+ if (namesleft > -1)
+ {
+ nam = algnIds.findIdMatch(realnam);
+ }
+
+ if (nam != null)
+ {
+ j.setElement(nam);
+ if (one2many.contains(nam))
+ {
+ // countOne2Many++;
+ // if (jalview.bin.Cache.log.isDebugEnabled())
+ // jalview.bin.Cache.log.debug("One 2 many relationship for
+ // "+nam.getName());
+ }
+ else
+ {
+ one2many.addElement(nam);
+ namesleft--;
+ }
+ }
+ else
+ {
+ j.setElement(new Sequence(realnam, "THISISAPLACEHLDER"));
+ j.setPlaceholder(true);
+ }
+ }
+ // if (jalview.bin.Cache.log.isDebugEnabled() && countOne2Many>0) {
+ // jalview.bin.Cache.log.debug("There were "+countOne2Many+" alignment
+ // sequence ids (out of "+one2many.size()+" unique ids) linked to two or
+ // more leaves.");
+ // }
+ // one2many.clear();
+ }
+
+ /**
+ * Generate a string representation of the Tree
+ *
+ * @return Newick File with all tree data available
+ */
+ public String print()
+ {
+ NewickFile fout = new NewickFile(getTopNode());
+
+ return fout.print(hasBootstrap(), hasDistances(),
+ hasRootDistance()); // output all data available for tree
+ }
+
+ /**
+ *
+ * used when the alignment associated to a tree has changed.
+ *
+ * @param list
+ * Sequence set to be associated with tree nodes
+ */
+ public void updatePlaceHolders(List<SequenceI> list)
+ {
+ Vector<SequenceNode> leaves = findLeaves(top);
+
+ int sz = leaves.size();
+ SequenceIdMatcher seqmatcher = null;
+ int i = 0;
+
+ while (i < sz)
+ {
+ SequenceNode leaf = leaves.elementAt(i++);
+
+ if (list.contains(leaf.element()))
+ {
+ leaf.setPlaceholder(false);
+ }
+ else
+ {
+ if (seqmatcher == null)
+ {
+ // Only create this the first time we need it
+ SequenceI[] seqs = new SequenceI[list.size()];
+
+ for (int j = 0; j < seqs.length; j++)
+ {
+ seqs[j] = list.get(j);
+ }
+
+ seqmatcher = new SequenceIdMatcher(seqs);
+ }
+
+ SequenceI nam = seqmatcher.findIdMatch(leaf.getName());
+
+ if (nam != null)
+ {
+ if (!leaf.isPlaceholder())
+ {
+ // remapping the node to a new sequenceI - should remove any refs to
+ // old one.
+ // TODO - make many sequenceI to one leaf mappings possible!
+ // (JBPNote)
+ }
+ leaf.setPlaceholder(false);
+ leaf.setElement(nam);
+ }
+ else
+ {
+ if (!leaf.isPlaceholder())
+ {
+ // Construct a new placeholder sequence object for this leaf
+ leaf.setElement(new Sequence(leaf.getName(),
+ "THISISAPLACEHLDER"));
+ }
+ leaf.setPlaceholder(true);
+
+ }
+ }
+ }
+ }
+
+ /**
+ * rename any nodes according to their associated sequence. This will modify
+ * the tree's metadata! (ie the original NewickFile or newly generated
+ * BinaryTree's label data)
+ */
+ public void renameAssociatedNodes()
+ {
+ applyToNodes(new NodeTransformI()
+ {
+
+ @Override
+ public void transform(BinaryNode nd)
+ {
+ Object el = nd.element();
+ if (el != null && el instanceof SequenceI)
+ {
+ nd.setName(((SequenceI) el).getName());
+ }
+ }
+ });
+ }
+
+ /**
+ * Search for leaf nodes below (or at) the given node
+ *
+ * @param nd
+ * root node to search from
+ *
+ * @return
+ */
+ public Vector<SequenceNode> findLeaves(SequenceNode nd)
+ {
+ Vector<SequenceNode> leaves = new Vector<SequenceNode>();
+ findLeaves(nd, leaves);
+ return leaves;
+ }
+
+ /**
+ * Search for leaf nodes.
+ *
+ * @param nd
+ * root node to search from
+ * @param leaves
+ * Vector of leaves to add leaf node objects too.
+ *
+ * @return Vector of leaf nodes on binary tree
+ */
+ Vector<SequenceNode> findLeaves(SequenceNode nd,
+ Vector<SequenceNode> leaves)
+ {
+ if (nd == null)
+ {
+ return leaves;
+ }
+
+ if ((nd.left() == null) && (nd.right() == null)) // Interior node
+ // detection
+ {
+ leaves.addElement(nd);
+
+ return leaves;
+ }
+ else
+ {
+ /*
+ * TODO: Identify internal nodes... if (node.isSequenceLabel()) {
+ * leaves.addElement(node); }
+ */
+ findLeaves((SequenceNode) nd.left(), leaves);
+ findLeaves((SequenceNode) nd.right(), leaves);
+ }
+
+ return leaves;
+ }
+
+ /**
+ * printNode is mainly for debugging purposes.
+ *
+ * @param nd
+ * SequenceNode
+ */
+ void printNode(SequenceNode nd)
+ {
+ if (nd == null)
+ {
+ return;
+ }
+
+ if ((nd.left() == null) && (nd.right() == null))
+ {
+ System.out.println("Leaf = " + ((SequenceI) nd.element()).getName());
+ System.out.println("Dist " + nd.dist);
+ System.out.println("Boot " + nd.getBootstrap());
+ }
+ else
+ {
+ System.out.println("Dist " + nd.dist);
+ printNode((SequenceNode) nd.left());
+ printNode((SequenceNode) nd.right());
+ }
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ public double getMaxHeight()
+ {
+ return maxheight;
+ }
+
+ /**
+ * Makes a list of groups, where each group is represented by a node whose
+ * height (distance from the root node), as a fraction of the height of the
+ * whole tree, is greater than the given threshold. This corresponds to
+ * selecting the nodes immediately to the right of a vertical line
+ * partitioning the tree (if the tree is drawn with root to the left). Each
+ * such node represents a group that contains all of the sequences linked to
+ * the child leaf nodes.
+ *
+ * @param threshold
+ * @see #getGroups()
+ */
+ public List<SequenceNode> groupNodes(float threshold)
+ {
+ List<SequenceNode> groups = new ArrayList<SequenceNode>();
+ _groupNodes(groups, getTopNode(), threshold);
+ return groups;
+ }
+
+ protected void _groupNodes(List<SequenceNode> groups, SequenceNode nd,
+ float threshold)
+ {
+ if (nd == null)
+ {
+ return;
+ }
+
+ if ((nd.height / maxheight) > threshold)
+ {
+ groups.add(nd);
+ }
+ else
+ {
+ _groupNodes(groups, (SequenceNode) nd.left(), threshold);
+ _groupNodes(groups, (SequenceNode) nd.right(), threshold);
+ }
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param nd
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ public double findHeight(SequenceNode nd)
+ {
+ if (nd == null)
+ {
+ return maxheight;
+ }
+
+ if ((nd.left() == null) && (nd.right() == null))
+ {
+ nd.height = ((SequenceNode) nd.parent()).height + nd.dist;
+
+ if (nd.height > maxheight)
+ {
+ return nd.height;
+ }
+ else
+ {
+ return maxheight;
+ }
+ }
+ else
+ {
+ if (nd.parent() != null)
+ {
+ nd.height = ((SequenceNode) nd.parent()).height + nd.dist;
+ }
+ else
+ {
+ maxheight = 0;
+ nd.height = (float) 0.0;
+ }
+
+ maxheight = findHeight((SequenceNode) (nd.left()));
+ maxheight = findHeight((SequenceNode) (nd.right()));
+ }
+
+ return maxheight;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param nd
+ * DOCUMENT ME!
+ */
+ void printN(SequenceNode nd)
+ {
+ if (nd == null)
+ {
+ return;
+ }
+
+ if ((nd.left() != null) && (nd.right() != null))
+ {
+ printN((SequenceNode) nd.left());
+ printN((SequenceNode) nd.right());
+ }
+ else
+ {
+ System.out.println(" name = " + ((SequenceI) nd.element()).getName());
+ }
+
+ System.out.println(" dist = " + nd.dist + " " + nd.count + " "
+ + nd.height);
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param nd
+ * DOCUMENT ME!
+ */
+ public void reCount(SequenceNode nd)
+ {
+ ycount = 0;
+ // _lycount = 0;
+ // _lylimit = this.node.size();
+ _reCount(nd);
+ }
+
+ // private long _lycount = 0, _lylimit = 0;
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param nd
+ * DOCUMENT ME!
+ */
+ void _reCount(SequenceNode nd)
+ {
+ // if (_lycount<_lylimit)
+ // {
+ // System.err.println("Warning: depth of _recount greater than number of nodes.");
+ // }
+ if (nd == null)
+ {
+ return;
+ }
+ // _lycount++;
+
+ if ((nd.left() != null) && (nd.right() != null))
+ {
+
+ _reCount((SequenceNode) nd.left());
+ _reCount((SequenceNode) nd.right());
+
+ SequenceNode l = (SequenceNode) nd.left();
+ SequenceNode r = (SequenceNode) nd.right();
+
+ nd.count = l.count + r.count;
+ nd.ycount = (l.ycount + r.ycount) / 2;
+ }
+ else
+ {
+ nd.count = 1;
+ nd.ycount = ycount++;
+ }
+ // _lycount--;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param nd
+ * DOCUMENT ME!
+ */
+ public void swapNodes(SequenceNode nd)
+ {
+ if (nd == null)
+ {
+ return;
+ }
+
+ SequenceNode tmp = (SequenceNode) nd.left();
+
+ nd.setLeft(nd.right());
+ nd.setRight(tmp);
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param nd
+ * DOCUMENT ME!
+ * @param dir
+ * DOCUMENT ME!
+ */
+ void changeDirection(SequenceNode nd, SequenceNode dir)
+ {
+ if (nd == null)
+ {
+ return;
+ }
+
+ if (nd.parent() != top)
+ {
+ changeDirection((SequenceNode) nd.parent(), nd);
+
+ SequenceNode tmp = (SequenceNode) nd.parent();
+
+ if (dir == nd.left())
+ {
+ nd.setParent(dir);
+ nd.setLeft(tmp);
+ }
+ else if (dir == nd.right())
+ {
+ nd.setParent(dir);
+ nd.setRight(tmp);
+ }
+ }
+ else
+ {
+ if (dir == nd.left())
+ {
+ nd.setParent(nd.left());
+
+ if (top.left() == nd)
+ {
+ nd.setRight(top.right());
+ }
+ else
+ {
+ nd.setRight(top.left());
+ }
+ }
+ else
+ {
+ nd.setParent(nd.right());
+
+ if (top.left() == nd)
+ {
+ nd.setLeft(top.right());
+ }
+ else
+ {
+ nd.setLeft(top.left());
+ }
+ }
+ }
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ public SequenceNode getTopNode()
+ {
+ return top;
+ }
+
+ /**
+ *
+ * @return true if tree has real distances
+ */
+ public boolean hasDistances()
+ {
+ return hasDistances;
+ }
+
+ /**
+ *
+ * @return true if tree has real bootstrap values
+ */
+ public boolean hasBootstrap()
+ {
+ return hasBootstrap;
+ }
+
+ public boolean hasRootDistance()
+ {
+ return hasRootDistance;
+ }
+
+ /**
+ * apply the given transform to all the nodes in the tree.
+ *
+ * @param nodeTransformI
+ */
+ public void applyToNodes(NodeTransformI nodeTransformI)
+ {
+ for (Enumeration<SequenceNode> nodes = node.elements(); nodes
+ .hasMoreElements(); nodeTransformI.transform(nodes
+ .nextElement()))
+ {
+ ;
+ }
+ }
+
+ public AlignmentView getOriginalData()
+ {
+ return seqData;
+ }
+}
--- /dev/null
+package jalview.analysis.scoremodels;
+
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.AlignmentView;
+import jalview.math.MatrixI;
+
+public abstract class DistanceScoreModel implements ScoreModelI
+{
+ /**
+ * A similarity score is calculated by first computing a distance score, and
+ * then reversing the min-max range of the score values
+ */
+ @Override
+ public MatrixI findSimilarities(AlignmentView seqData,
+ SimilarityParamsI options)
+ {
+ MatrixI distances = findDistances(seqData, options);
+
+ MatrixI similarities = distanceToSimilarity(distances);
+
+ return similarities;
+ }
+
+ /**
+ * Converts distance scores to similarity scores, by reversing the range of
+ * score values so that max becomes min and vice versa. The input matrix is
+ * not modified.
+ *
+ * @param distances
+ */
+ public static MatrixI distanceToSimilarity(MatrixI distances)
+ {
+ MatrixI similarities = distances.copy();
+
+ similarities.reverseRange(false);
+
+ return similarities;
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.analysis.scoremodels;
+
+import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.SeqCigar;
+import jalview.datamodel.SequenceFeature;
+import jalview.math.Matrix;
+import jalview.math.MatrixI;
+import jalview.util.SetUtils;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class FeatureDistanceModel extends DistanceScoreModel
+{
+ private static final String NAME = "Sequence Feature Similarity";
+
+ private String description;
+
+ FeatureRenderer fr;
+
+ /**
+ * Constructor
+ */
+ public FeatureDistanceModel()
+ {
+ }
+
+ @Override
+ public ScoreModelI getInstance(AlignmentViewPanel view)
+ {
+ FeatureDistanceModel instance;
+ try
+ {
+ instance = this.getClass().newInstance();
+ instance.configureFromAlignmentView(view);
+ return instance;
+ } catch (InstantiationException | IllegalAccessException e)
+ {
+ System.err.println("Error in " + getClass().getName()
+ + ".getInstance(): " + e.getMessage());
+ return null;
+ }
+ }
+
+ boolean configureFromAlignmentView(AlignmentViewPanel view)
+
+ {
+ fr = view.cloneFeatureRenderer();
+ return true;
+ }
+
+ /**
+ * Calculates a distance measure [i][j] between each pair of sequences as the
+ * average number of features they have but do not share. That is, find the
+ * features each sequence pair has at each column, ignore feature types they
+ * have in common, and count the rest. The totals are normalised by the number
+ * of columns processed.
+ * <p>
+ * The parameters argument provides settings for treatment of gap-residue
+ * aligned positions, and whether the score is over the longer or shorter of
+ * each pair of sequences
+ *
+ * @param seqData
+ * @param params
+ */
+ @Override
+ public MatrixI findDistances(AlignmentView seqData,
+ SimilarityParamsI params)
+ {
+ SeqCigar[] seqs = seqData.getSequences();
+ int noseqs = seqs.length;
+ int cpwidth = 0;// = seqData.getWidth();
+ double[][] distances = new double[noseqs][noseqs];
+ List<String> dft = null;
+ if (fr != null)
+ {
+ dft = fr.getDisplayedFeatureTypes();
+ }
+ if (dft == null || dft.isEmpty())
+ {
+ return new Matrix(distances);
+ }
+
+ // need to get real position for view position
+ int[] viscont = seqData.getVisibleContigs();
+
+ /*
+ * scan each column, compute and add to each distance[i, j]
+ * the number of feature types that seqi and seqj do not share
+ */
+ for (int vc = 0; vc < viscont.length; vc += 2)
+ {
+ for (int cpos = viscont[vc]; cpos <= viscont[vc + 1]; cpos++)
+ {
+ cpwidth++;
+
+ /*
+ * first record feature types in this column for each sequence
+ */
+ Map<SeqCigar, Set<String>> sfap = findFeatureTypesAtColumn(
+ seqs, cpos);
+
+ /*
+ * count feature types on either i'th or j'th sequence but not both
+ * and add this 'distance' measure to the total for [i, j] for j > i
+ */
+ for (int i = 0; i < (noseqs - 1); i++)
+ {
+ for (int j = i + 1; j < noseqs; j++)
+ {
+ SeqCigar sc1 = seqs[i];
+ SeqCigar sc2 = seqs[j];
+ Set<String> set1 = sfap.get(sc1);
+ Set<String> set2 = sfap.get(sc2);
+ boolean gap1 = set1 == null;
+ boolean gap2 = set2 == null;
+
+ /*
+ * gap-gap always scores zero
+ * residue-residue is always scored
+ * include gap-residue score if params say to do so
+ */
+ if ((!gap1 && !gap2) || params.includeGaps())
+ {
+ int seqDistance = SetUtils.countDisjunction(set1, set2);
+ distances[i][j] += seqDistance;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * normalise the distance scores (summed over columns) by the
+ * number of visible columns used in the calculation
+ * and fill in the bottom half of the matrix
+ */
+ // TODO JAL-2424 cpwidth may be out by 1 - affects scores but not tree shape
+ for (int i = 0; i < noseqs; i++)
+ {
+ for (int j = i + 1; j < noseqs; j++)
+ {
+ distances[i][j] /= cpwidth;
+ distances[j][i] = distances[i][j];
+ }
+ }
+ return new Matrix(distances);
+ }
+
+ /**
+ * Builds and returns a map containing a (possibly empty) list (one per
+ * SeqCigar) of visible feature types at the given column position. The map
+ * has no entry for sequences which are gapped at the column position.
+ *
+ * @param seqs
+ * @param columnPosition
+ * @return
+ */
+ protected Map<SeqCigar, Set<String>> findFeatureTypesAtColumn(
+ SeqCigar[] seqs, int columnPosition)
+ {
+ Map<SeqCigar, Set<String>> sfap = new HashMap<SeqCigar, Set<String>>();
+ for (SeqCigar seq : seqs)
+ {
+ int spos = seq.findPosition(columnPosition);
+ if (spos != -1)
+ {
+ Set<String> types = new HashSet<String>();
+ List<SequenceFeature> sfs = fr.findFeaturesAtRes(seq.getRefSeq(),
+ spos);
+ for (SequenceFeature sf : sfs)
+ {
+ types.add(sf.getType());
+ }
+ sfap.put(seq, types);
+ }
+ }
+ return sfap;
+ }
+
+ @Override
+ public String getName()
+ {
+ return NAME;
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return description;
+ }
+
+ @Override
+ public boolean isDNA()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isProtein()
+ {
+ return true;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Score between sequences based on hamming distance between binary vectors marking features displayed at each column";
+ }
+}
+++ /dev/null
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- *
- * This file is part of Jalview.
- *
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-package jalview.analysis.scoremodels;
-
-import jalview.api.analysis.ScoreModelI;
-import jalview.api.analysis.ViewBasedAnalysisI;
-import jalview.datamodel.AlignmentView;
-import jalview.datamodel.SeqCigar;
-import jalview.datamodel.SequenceFeature;
-
-import java.util.ArrayList;
-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<String> dft = fr.getDisplayedFeatureTypes();
- nofeats = dft.size();
- SeqCigar[] seqs = seqData.getSequences();
- int noseqs = seqs.length;
- int cpwidth = 0;// = 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;
- }
- // need to get real position for view position
- int[] viscont = seqData.getVisibleContigs();
- for (int vc = 0; vc < viscont.length; vc += 2)
- {
-
- for (int cpos = viscont[vc]; cpos <= viscont[vc + 1]; cpos++)
- {
- cpwidth++;
- // get visible features at cpos under view's display settings and
- // compare them
- List<Hashtable<String, SequenceFeature>> sfap = new ArrayList<Hashtable<String, SequenceFeature>>();
- for (int i = 0; i < noseqs; i++)
- {
- Hashtable<String, SequenceFeature> types = new Hashtable<String, SequenceFeature>();
- int spos = seqs[i].findPosition(cpos);
- if (spos != -1)
- {
- List<SequenceFeature> sfs = fr.findFeaturesAtRes(
- seqs[i].getRefSeq(), spos);
- 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<String, SequenceFeature> 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;
- }
-
- @Override
- public String toString()
- {
- return "Score between sequences based on hamming distance between binary vectors marking features displayed at each column";
- }
-}
--- /dev/null
+package jalview.analysis.scoremodels;
+
+import jalview.api.AlignmentViewPanel;
+import jalview.api.analysis.PairwiseScoreModelI;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.AlignmentView;
+import jalview.math.Matrix;
+import jalview.math.MatrixI;
+import jalview.util.Comparison;
+
+/**
+ * A class to provide sequence pairwise similarity based on residue identity.
+ * Instances of this class are immutable and thread-safe, so the same object is
+ * returned from calls to getInstance().
+ */
+public class PIDModel extends SimilarityScoreModel implements
+ PairwiseScoreModelI
+{
+ private static final String NAME = "PID";
+
+ /**
+ * Constructor
+ */
+ public PIDModel()
+ {
+ }
+
+ @Override
+ public String getName()
+ {
+ return NAME;
+ }
+
+ /**
+ * Answers null for description. If a display name is needed, use getName() or
+ * an internationalized string built from the name.
+ */
+ @Override
+ public String getDescription()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isDNA()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isProtein()
+ {
+ return true;
+ }
+
+ /**
+ * Answers 1 if c and d are the same residue (ignoring case), and not gap
+ * characters. Answers 0 for non-matching or gap characters.
+ */
+ @Override
+ public float getPairwiseScore(char c, char d)
+ {
+ c = toUpper(c);
+ d = toUpper(d);
+ if (c == d && !Comparison.isGap(c))
+ {
+ return 1f;
+ }
+ return 0f;
+ }
+
+ /**
+ * @param c
+ */
+ protected static char toUpper(char c)
+ {
+ if ('a' <= c && c <= 'z')
+ {
+ c += 'A' - 'a';
+ }
+ return c;
+ }
+
+ /**
+ * Computes similarity scores based on pairwise percentage identity of
+ * sequences. For consistency with Jalview 2.10.1's SeqSpace mode PCA
+ * calculation, the percentage scores are rescaled to the width of the
+ * sequences (as if counts of identical residues). This method is thread-safe.
+ */
+ @Override
+ public MatrixI findSimilarities(AlignmentView seqData,
+ SimilarityParamsI options)
+ {
+ String[] seqs = seqData.getSequenceStrings(Comparison.GAP_DASH);
+
+ MatrixI result = findSimilarities(seqs, options);
+
+ result.multiply(seqData.getWidth() / 100d);
+
+ return result;
+ }
+
+ /**
+ * A distance score is computed in the usual way (by reversing the range of
+ * the similarity score results), and then rescaled to percentage values
+ * (reversing the rescaling to count values done in findSimilarities). This
+ * method is thread-safe.
+ */
+ @Override
+ public MatrixI findDistances(AlignmentView seqData,
+ SimilarityParamsI options)
+ {
+ MatrixI result = super.findDistances(seqData, options);
+
+ if (seqData.getWidth() != 0)
+ {
+ result.multiply(100d / seqData.getWidth());
+ }
+
+ return result;
+ }
+
+ /**
+ * Compute percentage identity scores, using the gap treatment and
+ * normalisation specified by the options parameter
+ *
+ * @param seqs
+ * @param options
+ * @return
+ */
+ protected MatrixI findSimilarities(String[] seqs,
+ SimilarityParamsI options)
+ {
+ // TODO reuse code in ScoreMatrix instead somehow
+ double[][] values = new double[seqs.length][];
+ for (int row = 0; row < seqs.length; row++)
+ {
+ values[row] = new double[seqs.length];
+ for (int col = 0; col < seqs.length; col++)
+ {
+ double total = computePID(seqs[row], seqs[col], options);
+ values[row][col] = total;
+ }
+ }
+ return new Matrix(values);
+ }
+
+ /**
+ * Computes a percentage identity for two sequences, using the algorithm
+ * choices specified by the options parameter
+ *
+ * @param seq1
+ * @param seq2
+ * @param options
+ * @return
+ */
+ public static double computePID(String seq1, String seq2,
+ SimilarityParamsI options)
+ {
+ int len1 = seq1.length();
+ int len2 = seq2.length();
+ int width = Math.max(len1, len2);
+ int total = 0;
+ int divideBy = 0;
+
+ for (int i = 0; i < width; i++)
+ {
+ if (i >= len1 || i >= len2)
+ {
+ /*
+ * off the end of one sequence; stop if we are only matching
+ * on the shorter sequence length, else treat as trailing gap
+ */
+ if (options.denominateByShortestLength())
+ {
+ break;
+ }
+ if (options.includeGaps())
+ {
+ divideBy++;
+ }
+ if (options.matchGaps())
+ {
+ total++;
+ }
+ continue;
+ }
+ char c1 = seq1.charAt(i);
+ char c2 = seq2.charAt(i);
+ boolean gap1 = Comparison.isGap(c1);
+ boolean gap2 = Comparison.isGap(c2);
+
+ if (gap1 && gap2)
+ {
+ /*
+ * gap-gap: include if options say so, if so
+ * have to score as identity; else ignore
+ */
+ if (options.includeGappedColumns())
+ {
+ divideBy++;
+ total++;
+ }
+ continue;
+ }
+
+ if (gap1 || gap2)
+ {
+ /*
+ * gap-residue: include if options say so,
+ * count as match if options say so
+ */
+ if (options.includeGaps())
+ {
+ divideBy++;
+ }
+ if (options.matchGaps())
+ {
+ total++;
+ }
+ continue;
+ }
+
+ /*
+ * remaining case is gap-residue
+ */
+ if (toUpper(c1) == toUpper(c2))
+ {
+ total++;
+ }
+ divideBy++;
+ }
+
+ return divideBy == 0 ? 0D : 100D * total / divideBy;
+ }
+
+ @Override
+ public ScoreModelI getInstance(AlignmentViewPanel avp)
+ {
+ return this;
+ }
+}
+++ /dev/null
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- *
- * This file is part of Jalview.
- *
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-package jalview.analysis.scoremodels;
-
-import jalview.api.analysis.ScoreModelI;
-import jalview.datamodel.AlignmentView;
-import jalview.util.Comparison;
-
-public class PIDScoreModel implements ScoreModelI
-{
-
- @Override
- public float[][] findDistances(AlignmentView seqData)
- {
- String[] sequenceString = seqData
- .getSequenceStrings(Comparison.GapChars.charAt(0));
- int noseqs = sequenceString.length;
- float[][] distance = new float[noseqs][noseqs];
- for (int i = 0; i < (noseqs - 1); i++)
- {
- for (int j = i; j < noseqs; j++)
- {
- if (j == i)
- {
- distance[i][i] = 0;
- }
- else
- {
- distance[i][j] = 100 - Comparison.PID(sequenceString[i],
- sequenceString[j]);
-
- distance[j][i] = distance[i][j];
- }
- }
- }
- return distance;
- }
-
- @Override
- public String getName()
- {
- return "PID";
- }
-
- @Override
- public boolean isDNA()
- {
- return true;
- }
-
- @Override
- public boolean isProtein()
- {
- return true;
- }
-
-}
+++ /dev/null
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- *
- * This file is part of Jalview.
- *
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-package jalview.analysis.scoremodels;
-
-import jalview.api.analysis.ScoreModelI;
-import jalview.datamodel.AlignmentView;
-import jalview.util.Comparison;
-
-public abstract class PairwiseSeqScoreModel implements ScoreModelI
-{
- abstract public int getPairwiseScore(char c, char d);
-
- public float[][] findDistances(AlignmentView seqData)
- {
- String[] sequenceString = seqData
- .getSequenceStrings(Comparison.GapChars.charAt(0));
- int noseqs = sequenceString.length;
- float[][] distance = new float[noseqs][noseqs];
-
- int maxscore = 0;
- int end = sequenceString[0].length();
- for (int i = 0; i < (noseqs - 1); i++)
- {
- for (int j = i; j < noseqs; j++)
- {
- int score = 0;
-
- for (int k = 0; k < end; k++)
- {
- try
- {
- score += getPairwiseScore(sequenceString[i].charAt(k),
- sequenceString[j].charAt(k));
- } catch (Exception ex)
- {
- System.err.println("err creating " + getName() + " tree");
- ex.printStackTrace();
- }
- }
-
- distance[i][j] = (float) score;
-
- if (score > maxscore)
- {
- maxscore = score;
- }
- }
- }
-
- for (int i = 0; i < (noseqs - 1); i++)
- {
- for (int j = i; j < noseqs; j++)
- {
- distance[i][j] = (float) maxscore - distance[i][j];
- distance[j][i] = distance[i][j];
- }
- }
- return distance;
- }
-
- abstract public int[][] getMatrix();
-}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.analysis.scoremodels;
+
+import jalview.api.AlignmentViewPanel;
+import jalview.api.analysis.PairwiseScoreModelI;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.AlignmentView;
+import jalview.math.Matrix;
+import jalview.math.MatrixI;
+import jalview.util.Comparison;
+
+import java.util.Arrays;
+
+/**
+ * A class that models a substitution score matrix for any given alphabet of
+ * symbols. Instances of this class are immutable and thread-safe, so the same
+ * object is returned from calls to getInstance().
+ */
+public class ScoreMatrix extends SimilarityScoreModel implements
+ PairwiseScoreModelI
+{
+ private static final char GAP_CHARACTER = Comparison.GAP_DASH;
+
+ /*
+ * an arbitrary score to assign for identity of an unknown symbol
+ * (this is the value on the diagonal in the * column of the NCBI matrix)
+ * (though a case could be made for using the minimum diagonal value)
+ */
+ private static final int UNKNOWN_IDENTITY_SCORE = 1;
+
+ /*
+ * Jalview 2.10.1 treated gaps as X (peptide) or N (nucleotide)
+ * for pairwise scoring; 2.10.2 uses gap score (last column) in
+ * score matrix (JAL-2397)
+ * Set this flag to true (via Groovy) for 2.10.1 behaviour
+ */
+ private static boolean scoreGapAsAny = false;
+
+ public static final short UNMAPPED = (short) -1;
+
+ private static final String BAD_ASCII_ERROR = "Unexpected character %s in getPairwiseScore";
+
+ private static final int MAX_ASCII = 127;
+
+ /*
+ * the name of the model as shown in menus
+ * each score model in use should have a unique name
+ */
+ private String name;
+
+ /*
+ * a description for the model as shown in tooltips
+ */
+ private String description;
+
+ /*
+ * the characters that the model provides scores for
+ */
+ private char[] symbols;
+
+ /*
+ * the score matrix; both dimensions must equal the number of symbols
+ * matrix[i][j] is the substitution score for replacing symbols[i] with symbols[j]
+ */
+ private float[][] matrix;
+
+ /*
+ * quick lookup to convert from an ascii character value to the index
+ * of the corresponding symbol in the score matrix
+ */
+ private short[] symbolIndex;
+
+ /*
+ * true for Protein Score matrix, false for dna score matrix
+ */
+ private boolean peptide;
+
+ private float minValue;
+
+ private float maxValue;
+
+ /**
+ * Constructor given a name, symbol alphabet, and matrix of scores for pairs
+ * of symbols. The matrix should be square and of the same size as the
+ * alphabet, for example 20x20 for a 20 symbol alphabet.
+ *
+ * @param theName
+ * Unique, human readable name for the matrix
+ * @param alphabet
+ * the symbols to which scores apply
+ * @param values
+ * Pairwise scores indexed according to the symbol alphabet
+ */
+ public ScoreMatrix(String theName, char[] alphabet, float[][] values)
+ {
+ this(theName, null, alphabet, values);
+ }
+
+ /**
+ * Constructor given a name, description, symbol alphabet, and matrix of
+ * scores for pairs of symbols. The matrix should be square and of the same
+ * size as the alphabet, for example 20x20 for a 20 symbol alphabet.
+ *
+ * @param theName
+ * Unique, human readable name for the matrix
+ * @param theDescription
+ * descriptive display name suitable for use in menus
+ * @param alphabet
+ * the symbols to which scores apply
+ * @param values
+ * Pairwise scores indexed according to the symbol alphabet
+ */
+ public ScoreMatrix(String theName, String theDescription,
+ char[] alphabet, float[][] values)
+ {
+ if (alphabet.length != values.length)
+ {
+ throw new IllegalArgumentException(
+ "score matrix size must match alphabet size");
+ }
+ for (float[] row : values)
+ {
+ if (row.length != alphabet.length)
+ {
+ throw new IllegalArgumentException(
+ "score matrix size must be square");
+ }
+ }
+
+ this.matrix = values;
+ this.name = theName;
+ this.description = theDescription;
+ this.symbols = alphabet;
+
+ symbolIndex = buildSymbolIndex(alphabet);
+
+ findMinMax();
+
+ /*
+ * crude heuristic for now...
+ */
+ peptide = alphabet.length >= 20;
+ }
+
+ /**
+ * Record the minimum and maximum score values
+ */
+ protected void findMinMax()
+ {
+ float min = Float.MAX_VALUE;
+ float max = -Float.MAX_VALUE;
+ if (matrix != null)
+ {
+ for (float[] row : matrix)
+ {
+ if (row != null)
+ {
+ for (float f : row)
+ {
+ min = Math.min(min, f);
+ max = Math.max(max, f);
+ }
+ }
+ }
+ }
+ minValue = min;
+ maxValue = max;
+ }
+
+ /**
+ * Returns an array A where A[i] is the position in the alphabet array of the
+ * character whose value is i. For example if the alphabet is { 'A', 'D', 'X'
+ * } then A['D'] = A[68] = 1.
+ * <p>
+ * Unmapped characters (not in the alphabet) get an index of -1.
+ * <p>
+ * Mappings are added automatically for lower case symbols (for non case
+ * sensitive scoring), unless they are explicitly present in the alphabet (are
+ * scored separately in the score matrix).
+ * <p>
+ * the gap character (space, dash or dot) included in the alphabet (if any) is
+ * recorded in a field
+ *
+ * @param alphabet
+ * @return
+ */
+ short[] buildSymbolIndex(char[] alphabet)
+ {
+ short[] index = new short[MAX_ASCII + 1];
+ Arrays.fill(index, UNMAPPED);
+ short pos = 0;
+ for (char c : alphabet)
+ {
+ if (c <= MAX_ASCII)
+ {
+ index[c] = pos;
+ }
+
+ /*
+ * also map lower-case character (unless separately mapped)
+ */
+ if (c >= 'A' && c <= 'Z')
+ {
+ short lowerCase = (short) (c + ('a' - 'A'));
+ if (index[lowerCase] == UNMAPPED)
+ {
+ index[lowerCase] = pos;
+ }
+ }
+ pos++;
+ }
+ return index;
+ }
+
+ @Override
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return description;
+ }
+
+ @Override
+ public boolean isDNA()
+ {
+ return !peptide;
+ }
+
+ @Override
+ public boolean isProtein()
+ {
+ return peptide;
+ }
+
+ /**
+ * Returns a copy of the score matrix as used in getPairwiseScore. If using
+ * this matrix directly, callers <em>must</em> also call
+ * <code>getMatrixIndex</code> in order to get the matrix index for each
+ * character (symbol).
+ *
+ * @return
+ * @see #getMatrixIndex(char)
+ */
+ public float[][] getMatrix()
+ {
+ float[][] v = new float[matrix.length][matrix.length];
+ for (int i = 0; i < matrix.length; i++)
+ {
+ v[i] = Arrays.copyOf(matrix[i], matrix[i].length);
+ }
+ return v;
+ }
+
+ /**
+ * Answers the matrix index for a given character, or -1 if unmapped in the
+ * matrix. Use this method only if using <code>getMatrix</code> in order to
+ * compute scores directly (without symbol lookup) for efficiency.
+ *
+ * @param c
+ * @return
+ * @see #getMatrix()
+ */
+ public int getMatrixIndex(char c)
+ {
+ if (c < symbolIndex.length)
+ {
+ return symbolIndex[c];
+ }
+ else
+ {
+ return UNMAPPED;
+ }
+ }
+
+ /**
+ * Returns the pairwise score for substituting c with d. If either c or d is
+ * an unexpected character, returns 1 for identity (c == d), else the minimum
+ * score value in the matrix.
+ */
+ @Override
+ public float getPairwiseScore(char c, char d)
+ {
+ if (c >= symbolIndex.length)
+ {
+ System.err.println(String.format(BAD_ASCII_ERROR, c));
+ return 0;
+ }
+ if (d >= symbolIndex.length)
+ {
+ System.err.println(String.format(BAD_ASCII_ERROR, d));
+ return 0;
+ }
+
+ int cIndex = symbolIndex[c];
+ int dIndex = symbolIndex[d];
+ if (cIndex != UNMAPPED && dIndex != UNMAPPED)
+ {
+ return matrix[cIndex][dIndex];
+ }
+
+ /*
+ * one or both symbols not found in the matrix
+ * currently scoring as 1 (for identity) or the minimum
+ * matrix score value (otherwise)
+ * (a case could be made for using minimum row/column value instead)
+ */
+ return c == d ? UNKNOWN_IDENTITY_SCORE : getMinimumScore();
+ }
+
+ /**
+ * pretty print the matrix
+ */
+ @Override
+ public String toString()
+ {
+ return outputMatrix(false);
+ }
+
+ /**
+ * Print the score matrix, optionally formatted as html, with the alphabet
+ * symbols as column headings and at the start of each row.
+ * <p>
+ * The non-html format should give an output which can be parsed as a score
+ * matrix file
+ *
+ * @param html
+ * @return
+ */
+ public String outputMatrix(boolean html)
+ {
+ StringBuilder sb = new StringBuilder(512);
+
+ /*
+ * heading row with alphabet
+ */
+ if (html)
+ {
+ sb.append("<table border=\"1\">");
+ sb.append(html ? "<tr><th></th>" : "");
+ }
+ else
+ {
+ sb.append("ScoreMatrix ").append(getName()).append("\n");
+ }
+ for (char sym : symbols)
+ {
+ if (html)
+ {
+ sb.append("<th> ").append(sym).append(" </th>");
+ }
+ else
+ {
+ sb.append("\t").append(sym);
+ }
+ }
+ sb.append(html ? "</tr>\n" : "\n");
+
+ /*
+ * table of scores
+ */
+ for (char c1 : symbols)
+ {
+ if (html)
+ {
+ sb.append("<tr><td>");
+ }
+ sb.append(c1).append(html ? "</td>" : "");
+ for (char c2 : symbols)
+ {
+ sb.append(html ? "<td>" : "\t")
+ .append(matrix[symbolIndex[c1]][symbolIndex[c2]])
+ .append(html ? "</td>" : "");
+ }
+ sb.append(html ? "</tr>\n" : "\n");
+ }
+ if (html)
+ {
+ sb.append("</table>");
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Answers the number of symbols coded for (also equal to the number of rows
+ * and columns of the score matrix)
+ *
+ * @return
+ */
+ public int getSize()
+ {
+ return symbols.length;
+ }
+
+ /**
+ * Computes an NxN matrix where N is the number of sequences, and entry [i, j]
+ * is sequence[i] pairwise multiplied with sequence[j], as a sum of scores
+ * computed using the current score matrix. For example
+ * <ul>
+ * <li>Sequences:</li>
+ * <li>FKL</li>
+ * <li>R-D</li>
+ * <li>QIA</li>
+ * <li>GWC</li>
+ * <li>Score matrix is BLOSUM62</li>
+ * <li>Gaps treated same as X (unknown)</li>
+ * <li>product [0, 0] = F.F + K.K + L.L = 6 + 5 + 4 = 15</li>
+ * <li>product [1, 1] = R.R + -.- + D.D = 5 + -1 + 6 = 10</li>
+ * <li>product [2, 2] = Q.Q + I.I + A.A = 5 + 4 + 4 = 13</li>
+ * <li>product [3, 3] = G.G + W.W + C.C = 6 + 11 + 9 = 26</li>
+ * <li>product[0, 1] = F.R + K.- + L.D = -3 + -1 + -3 = -8
+ * <li>and so on</li>
+ * </ul>
+ * This method is thread-safe.
+ */
+ @Override
+ public MatrixI findSimilarities(AlignmentView seqstrings,
+ SimilarityParamsI options)
+ {
+ char gapChar = scoreGapAsAny ? (seqstrings.isNa() ? 'N' : 'X')
+ : GAP_CHARACTER;
+ String[] seqs = seqstrings.getSequenceStrings(gapChar);
+ return findSimilarities(seqs, options);
+ }
+
+ /**
+ * Computes pairwise similarities of a set of sequences using the given
+ * parameters
+ *
+ * @param seqs
+ * @param params
+ * @return
+ */
+ protected MatrixI findSimilarities(String[] seqs, SimilarityParamsI params)
+ {
+ double[][] values = new double[seqs.length][];
+ for (int row = 0; row < seqs.length; row++)
+ {
+ values[row] = new double[seqs.length];
+ for (int col = 0; col < seqs.length; col++)
+ {
+ double total = computeSimilarity(seqs[row], seqs[col], params);
+ values[row][col] = total;
+ }
+ }
+ return new Matrix(values);
+ }
+
+ /**
+ * Calculates the pairwise similarity of two strings using the given
+ * calculation parameters
+ *
+ * @param seq1
+ * @param seq2
+ * @param params
+ * @return
+ */
+ protected double computeSimilarity(String seq1, String seq2,
+ SimilarityParamsI params)
+ {
+ int len1 = seq1.length();
+ int len2 = seq2.length();
+ double total = 0;
+
+ int width = Math.max(len1, len2);
+ for (int i = 0; i < width; i++)
+ {
+ if (i >= len1 || i >= len2)
+ {
+ /*
+ * off the end of one sequence; stop if we are only matching
+ * on the shorter sequence length, else treat as trailing gap
+ */
+ if (params.denominateByShortestLength())
+ {
+ break;
+ }
+ }
+
+ char c1 = i >= len1 ? GAP_CHARACTER : seq1.charAt(i);
+ char c2 = i >= len2 ? GAP_CHARACTER : seq2.charAt(i);
+ boolean gap1 = Comparison.isGap(c1);
+ boolean gap2 = Comparison.isGap(c2);
+
+ if (gap1 && gap2)
+ {
+ /*
+ * gap-gap: include if options say so, else ignore
+ */
+ if (!params.includeGappedColumns())
+ {
+ continue;
+ }
+ }
+ else if (gap1 || gap2)
+ {
+ /*
+ * gap-residue: score if options say so
+ */
+ if (!params.includeGaps())
+ {
+ continue;
+ }
+ }
+ float score = getPairwiseScore(c1, c2);
+ total += score;
+ }
+ return total;
+ }
+
+ /**
+ * Answers a hashcode computed from the symbol alphabet and the matrix score
+ * values
+ */
+ @Override
+ public int hashCode()
+ {
+ int hs = Arrays.hashCode(symbols);
+ for (float[] row : matrix)
+ {
+ hs = hs * 31 + Arrays.hashCode(row);
+ }
+ return hs;
+ }
+
+ /**
+ * Answers true if the argument is a ScoreMatrix with the same symbol alphabet
+ * and score values, else false
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof ScoreMatrix))
+ {
+ return false;
+ }
+ ScoreMatrix sm = (ScoreMatrix) obj;
+ if (Arrays.equals(symbols, sm.symbols)
+ && Arrays.deepEquals(matrix, sm.matrix))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the alphabet the matrix scores for, as a string of characters
+ *
+ * @return
+ */
+ String getSymbols()
+ {
+ return new String(symbols);
+ }
+
+ public float getMinimumScore()
+ {
+ return minValue;
+ }
+
+ public float getMaximumScore()
+ {
+ return maxValue;
+ }
+
+ @Override
+ public ScoreModelI getInstance(AlignmentViewPanel avp)
+ {
+ return this;
+ }
+}
--- /dev/null
+package jalview.analysis.scoremodels;
+
+import jalview.api.AlignmentViewPanel;
+import jalview.api.analysis.ScoreModelI;
+import jalview.io.DataSourceType;
+import jalview.io.FileParse;
+import jalview.io.ScoreMatrixFile;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * A class that can register and serve instances of ScoreModelI
+ */
+public class ScoreModels
+{
+ private final ScoreMatrix BLOSUM62;
+
+ private final ScoreMatrix PAM250;
+
+ private final ScoreMatrix DNA;
+
+ private static ScoreModels instance = new ScoreModels();
+
+ private Map<String, ScoreModelI> models;
+
+ public static ScoreModels getInstance()
+ {
+ return instance;
+ }
+
+ /**
+ * Private constructor to enforce use of singleton. Registers Jalview's
+ * "built-in" score models:
+ * <ul>
+ * <li>BLOSUM62</li>
+ * <li>PAM250</li>
+ * <li>PID</li>
+ * <li>DNA</li>
+ * <li>Sequence Feature Similarity</li>
+ * </ul>
+ */
+ private ScoreModels()
+ {
+ /*
+ * using LinkedHashMap keeps models ordered as added
+ */
+ models = new LinkedHashMap<String, ScoreModelI>();
+ BLOSUM62 = loadScoreMatrix("scoreModel/blosum62.scm");
+ PAM250 = loadScoreMatrix("scoreModel/pam250.scm");
+ registerScoreModel(new PIDModel());
+ DNA = loadScoreMatrix("scoreModel/dna.scm");
+ registerScoreModel(new FeatureDistanceModel());
+ }
+
+ /**
+ * Tries to load a score matrix from the given resource file, and if
+ * successful, registers it.
+ *
+ * @param string
+ * @return
+ */
+ ScoreMatrix loadScoreMatrix(String resourcePath)
+ {
+ try
+ {
+ /*
+ * delegate parsing to ScoreMatrixFile
+ */
+ FileParse fp = new FileParse(resourcePath, DataSourceType.CLASSLOADER);
+ ScoreMatrix sm = new ScoreMatrixFile(fp).parseMatrix();
+ registerScoreModel(sm);
+ return sm;
+ } catch (IOException e)
+ {
+ System.err.println("Error reading " + resourcePath + ": "
+ + e.getMessage());
+ }
+ return null;
+ }
+
+ /**
+ * Answers an iterable set of the registered score models. Currently these are
+ * returned in the order in which they were registered.
+ *
+ * @return
+ */
+ public Iterable<ScoreModelI> getModels()
+ {
+ return models.values();
+ }
+
+ /**
+ * Returns an instance of a score model for the given name. If the model is of
+ * 'view dependent' type (e.g. feature similarity), instantiates a new
+ * instance configured for the given view. Otherwise returns a cached instance
+ * of the score model.
+ *
+ * @param name
+ * @param avp
+ * @return
+ */
+ public ScoreModelI getScoreModel(String name, AlignmentViewPanel avp)
+ {
+ ScoreModelI model = models.get(name);
+ return model == null ? null : model.getInstance(avp);
+ }
+
+ public void registerScoreModel(ScoreModelI sm)
+ {
+ ScoreModelI sm2 = models.get(sm.getName());
+ if (sm2 != null)
+ {
+ System.err.println("Warning: replacing score model " + sm2.getName());
+ }
+ models.put(sm.getName(), sm);
+ }
+
+ /**
+ * Returns the default peptide or nucleotide score model, currently BLOSUM62
+ * or DNA
+ *
+ * @param forPeptide
+ * @return
+ */
+ public ScoreMatrix getDefaultModel(boolean forPeptide)
+ {
+ return forPeptide ? BLOSUM62 : DNA;
+ }
+
+ public ScoreMatrix getBlosum62()
+ {
+ return BLOSUM62;
+ }
+
+ public ScoreMatrix getPam250()
+ {
+ return PAM250;
+ }
+}
--- /dev/null
+package jalview.analysis.scoremodels;
+
+import jalview.api.analysis.SimilarityParamsI;
+
+/**
+ * A class to hold parameters that configure the pairwise similarity
+ * calculation. Based on the paper
+ *
+ * <pre>
+ * Quantification of the variation in percentage identity for protein sequence alignments
+ * Raghava, GP and Barton, GJ
+ * BMC Bioinformatics. 2006 Sep 19;7:415
+ * </pre>
+ *
+ * @see https://www.ncbi.nlm.nih.gov/pubmed/16984632
+ */
+public class SimilarityParams implements SimilarityParamsI
+{
+ /**
+ * Based on Jalview's Comparison.PID method, which includes gaps and counts
+ * them as matching; it counts over the length of the shorter sequence
+ */
+ public static final SimilarityParamsI Jalview = new SimilarityParams(
+ true, true, true, true);
+
+ /**
+ * 'SeqSpace' mode PCA calculation includes gaps but does not count them as
+ * matching; it uses the longest sequence length
+ */
+ public static final SimilarityParamsI SeqSpace = new SimilarityParams(
+ true, false, true, true);
+
+ /**
+ * as described in the Raghava-Barton paper
+ * <ul>
+ * <li>ignores gap-gap</li>
+ * <li>does not score gap-residue</li>
+ * <li>includes gap-residue in lengths</li>
+ * <li>matches on longer of two sequences</li>
+ * </ul>
+ */
+ public static final SimilarityParamsI PID1 = new SimilarityParams(false,
+ false, true, false);
+
+ /**
+ * as described in the Raghava-Barton paper
+ * <ul>
+ * <li>ignores gap-gap</li>
+ * <li>ignores gap-residue</li>
+ * <li>matches on longer of two sequences</li>
+ * </ul>
+ */
+ public static final SimilarityParamsI PID2 = new SimilarityParams(false,
+ false, false, false);
+
+ /**
+ * as described in the Raghava-Barton paper
+ * <ul>
+ * <li>ignores gap-gap</li>
+ * <li>ignores gap-residue</li>
+ * <li>matches on shorter of sequences only</li>
+ * </ul>
+ */
+ public static final SimilarityParamsI PID3 = new SimilarityParams(false,
+ false, false, true);
+
+ /**
+ * as described in the Raghava-Barton paper
+ * <ul>
+ * <li>ignores gap-gap</li>
+ * <li>does not score gap-residue</li>
+ * <li>includes gap-residue in lengths</li>
+ * <li>matches on shorter of sequences only</li>
+ * </ul>
+ */
+ public static final SimilarityParamsI PID4 = new SimilarityParams(false,
+ false, true, true);
+
+ private boolean includeGappedColumns;
+
+ private boolean matchGaps;
+
+ private boolean includeGaps;
+
+ private boolean denominateByShortestLength;
+
+ /**
+ * Constructor
+ *
+ * @param includeGapGap
+ * @param matchGapResidue
+ * @param includeGapResidue
+ * if true, gapped positions are counted for normalisation by length
+ * @param shortestLength
+ * if true, the denominator is the shorter sequence length (possibly
+ * including gaps)
+ */
+ public SimilarityParams(boolean includeGapGap, boolean matchGapResidue,
+ boolean includeGapResidue, boolean shortestLength)
+ {
+ includeGappedColumns = includeGapGap;
+ matchGaps = matchGapResidue;
+ includeGaps = includeGapResidue;
+ denominateByShortestLength = shortestLength;
+ }
+
+ @Override
+ public boolean includeGaps()
+ {
+ return includeGaps;
+ }
+
+ @Override
+ public boolean denominateByShortestLength()
+ {
+ return denominateByShortestLength;
+ }
+
+ @Override
+ public boolean includeGappedColumns()
+ {
+ return includeGappedColumns;
+ }
+
+ @Override
+ public boolean matchGaps()
+ {
+ return matchGaps;
+ }
+}
--- /dev/null
+package jalview.analysis.scoremodels;
+
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.AlignmentView;
+import jalview.math.MatrixI;
+
+public abstract class SimilarityScoreModel implements ScoreModelI
+{
+
+ /**
+ * Computed similarity scores are converted to distance scores by subtracting
+ * every value from the maximum value. That is, maximum similarity corresponds
+ * to zero distance, and smaller similarities to larger distances.
+ */
+ @Override
+ public MatrixI findDistances(AlignmentView seqData,
+ SimilarityParamsI options)
+ {
+ MatrixI similarities = findSimilarities(seqData, options);
+
+ MatrixI distances = similarityToDistance(similarities);
+
+ return distances;
+ }
+
+ /**
+ * Converts a matrix of similarity scores to distance scores, by reversing the
+ * range of the scores, mapping the maximum to zero. The input matrix is not
+ * modified.
+ *
+ * @param similarities
+ */
+ public static MatrixI similarityToDistance(MatrixI similarities)
+ {
+ MatrixI distances = similarities.copy();
+
+ distances.reverseRange(true);
+
+ return distances;
+ }
+
+}
package jalview.analysis.scoremodels;
import jalview.analysis.AlignSeq;
+import jalview.api.AlignmentViewPanel;
import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
import jalview.datamodel.AlignmentView;
import jalview.datamodel.SequenceI;
+import jalview.math.Matrix;
+import jalview.math.MatrixI;
import jalview.util.Comparison;
-public class SWScoreModel implements ScoreModelI
+/**
+ * A class that computes pairwise similarity scores using the Smith-Waterman
+ * alignment algorithm
+ */
+public class SmithWatermanModel extends SimilarityScoreModel
{
+ private static final String NAME = "Smith Waterman Score";
+
+ private String description;
+
+ /**
+ * Constructor
+ */
+ public SmithWatermanModel()
+ {
+ }
@Override
- public float[][] findDistances(AlignmentView seqData)
+ public MatrixI findSimilarities(AlignmentView seqData,
+ SimilarityParamsI options)
{
SequenceI[] sequenceString = seqData.getVisibleAlignment(
- Comparison.GapChars.charAt(0)).getSequencesArray();
+ Comparison.GAP_SPACE).getSequencesArray();
int noseqs = sequenceString.length;
- float[][] distance = new float[noseqs][noseqs];
+ double[][] distances = new double[noseqs][noseqs];
- float max = -1;
+ double max = -1;
for (int i = 0; i < (noseqs - 1); i++)
{
as.calcScoreMatrix();
as.traceAlignment();
as.printAlignment(System.out);
- distance[i][j] = (float) as.maxscore;
+ distances[i][j] = as.maxscore;
- if (max < distance[i][j])
+ if (max < distances[i][j])
{
- max = distance[i][j];
+ max = distances[i][j];
}
}
}
- for (int i = 0; i < (noseqs - 1); i++)
- {
- for (int j = i; j < noseqs; j++)
- {
- distance[i][j] = max - distance[i][j];
- distance[j][i] = distance[i][j];
- }
- }
-
- return distance;
+ return new Matrix(distances);
}
@Override
public String getName()
{
- return "Smith Waterman Score";
+ return NAME;
}
@Override
return true;
}
- public String toString()
+ @Override
+ public String getDescription()
+ {
+ return description;
+ }
+
+ @Override
+ public ScoreModelI getInstance(AlignmentViewPanel avp)
{
- return "Score between two sequences aligned with Smith Waterman with default Peptide/Nucleotide matrix";
+ return this;
}
}
import jalview.viewmodel.ViewportRanges;
import java.awt.Color;
+import java.awt.Font;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
* @return search results or null
*/
SearchResultsI getSearchResults();
+
+ /**
+ * Updates view settings with the given font. You may need to call
+ * AlignmentPanel.fontChanged to update the layout geometry.
+ *
+ * @param setGrid
+ * when true, charWidth/height is set according to font metrics
+ */
+ void setFont(Font newFont, boolean b);
+
+ /**
+ * Answers true if split screen protein and cDNA use the same font
+ *
+ * @return
+ */
+ boolean isProteinFontAsCdna();
+
+ /**
+ * Set the flag for whether split screen protein and cDNA use the same font
+ *
+ * @return
+ */
+ void setProteinFontAsCdna(boolean b);
}
--- /dev/null
+package jalview.api;
+
+public interface AlignmentColsCollectionI extends Iterable<Integer>
+{
+ /**
+ * Answers if the column at the given position is hidden.
+ *
+ * @param c
+ * the column index to check
+ * @return true if the column at the position is hidden
+ */
+ public boolean isHidden(int c);
+}
--- /dev/null
+package jalview.api;
+
+import jalview.datamodel.SequenceI;
+
+public interface AlignmentRowsCollectionI extends Iterable<Integer>
+{
+ /**
+ * Answers if the sequence at the given position is hidden.
+ *
+ * @param r
+ * the row index to check
+ * @return true if the sequence at r is hidden
+ */
+ public boolean isHidden(int r);
+
+ /**
+ * Answers the sequence at the given position in the alignment
+ *
+ * @param r
+ * the row index to locate
+ * @return the sequence
+ */
+ public SequenceI getSequence(int r);
+}
*/
package jalview.api;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceI;
/**
*
* @return
*/
- public ColumnSelection getColumnSelection();
+ public HiddenColumns getHiddenColumns();
/**
* Retrieves hidden sequences from a complex file parser
* @return Sequence<->Structure mapping as int[][]
* @throws SiftsException
*/
- public StringBuffer getMappingOutput(MappingOutputPojo mop)
+ public StringBuilder getMappingOutput(MappingOutputPojo mop)
throws SiftsException;
/**
* @return
*/
void setScaleProteinAsCdna(boolean b);
+
+ /**
+ * Answers true if split screen protein and cDNA use the same font
+ *
+ * @return
+ */
+ boolean isProteinFontAsCdna();
+
+ /**
+ * Set the flag for whether split screen protein and cDNA use the same font
+ *
+ * @return
+ */
+ void setProteinFontAsCdna(boolean b);
}
--- /dev/null
+package jalview.api.analysis;
+
+/**
+ * An interface that describes classes that can compute similarity (aka
+ * substitution) scores for pairs of residues
+ */
+public interface PairwiseScoreModelI
+{
+ /**
+ * Answers a similarity score between two sequence characters (for
+ * substitution of the first by the second). Typically the highest scores are
+ * for identity, and the lowest for substitution of a residue by one with very
+ * different properties.
+ *
+ * @param c
+ * @param d
+ * @return
+ */
+ abstract public float getPairwiseScore(char c, char d);
+ // TODO make this static when Java 8
+
+}
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- *
- * This file is part of Jalview.
- *
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
package jalview.api.analysis;
+import jalview.api.AlignmentViewPanel;
import jalview.datamodel.AlignmentView;
+import jalview.math.MatrixI;
public interface ScoreModelI
{
-
- float[][] findDistances(AlignmentView seqData);
-
+ /**
+ * Answers a name for the score model, suitable for display in menus. Names
+ * should be unique across score models in use.
+ *
+ * @return
+ * @see jalview.analysis.scoremodels.ScoreModels#forName(String)
+ */
String getName();
+ /**
+ * Answers an informative description of the model, suitable for use in
+ * tooltips. Descriptions may be internationalised, and need not be unique
+ * (but should be).
+ *
+ * @return
+ */
+ String getDescription();
+
+ /**
+ * Answers true if this model is applicable for nucleotide data (so should be
+ * shown in menus in that context)
+ *
+ * @return
+ */
boolean isDNA();
+ /**
+ * Answers true if this model is applicable for peptide data (so should be
+ * shown in menus in that context)
+ *
+ * @return
+ */
boolean isProtein();
+ // TODO getName, isDNA, isProtein can be static methods in Java 8
+
+ /**
+ * Returns a distance score for the given sequence regions, that is, a matrix
+ * whose value [i][j] is the distance of sequence i from sequence j by some
+ * measure. The options parameter provides configuration choices for how the
+ * similarity score is calculated.
+ *
+ * @param seqData
+ * @param options
+ * @return
+ */
+
+ MatrixI findDistances(AlignmentView seqData, SimilarityParamsI options);
+
+ /**
+ * Returns a similarity score for the given sequence regions, that is, a
+ * matrix whose value [i][j] is the similarity of sequence i to sequence j by
+ * some measure. The options parameter provides configuration choices for how
+ * the similarity score is calculated.
+ *
+ * @param seqData
+ * @param options
+ * @return
+ */
+ MatrixI findSimilarities(AlignmentView seqData, SimilarityParamsI options);
+
+ /**
+ * Returns a score model object configured for the given alignment view.
+ * Depending on the score model, this may just be a singleton instance, or a
+ * new instance configured with data from the view.
+ *
+ * @param avp
+ * @return
+ */
+ ScoreModelI getInstance(AlignmentViewPanel avp);
}
--- /dev/null
+package jalview.api.analysis;
+
+/**
+ * A description of options when computing percentage identity of two aligned
+ * sequences
+ */
+public interface SimilarityParamsI
+{
+ /**
+ * Answers true if gap-gap aligned positions should be included in the
+ * calculation
+ *
+ * @return
+ */
+ boolean includeGappedColumns();
+
+ /**
+ * Answers true if gap-residue alignment is considered a match
+ *
+ * @return
+ */
+ // TODO is this specific to a PID score only?
+ // score matrix will compute whatever is configured for gap-residue
+ boolean matchGaps();
+
+ /**
+ * Answers true if gaps are included in the calculation. This may affect the
+ * calculated score, the denominator (normalisation factor) of the score, or
+ * both. Gap-gap positions are included if this and includeGappedColumns both
+ * answer true.
+ *
+ * @return
+ */
+ boolean includeGaps();
+
+ /**
+ * Answers true if only the shortest sequence length is used to divide the
+ * total score, false if the longest sequence length
+ *
+ * @return
+ */
+ boolean denominateByShortestLength();
+}
import jalview.analysis.AlignmentSorter;
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.analysis.TreeBuilder;
+import jalview.analysis.scoremodels.PIDModel;
+import jalview.analysis.scoremodels.ScoreModels;
import jalview.api.AlignViewControllerGuiI;
import jalview.api.AlignViewControllerI;
import jalview.api.AlignViewportI;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceGroup;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
-import java.awt.MenuShortcut;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
}
public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
- ColumnSelection columnSelection, JalviewLite applet,
+ HiddenColumns hidden, JalviewLite applet,
String title, boolean embedded)
{
- this(al, hiddenSeqs, columnSelection, applet, title, embedded, true);
+ this(al, hiddenSeqs, hidden, applet, title, embedded, true);
}
public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
- ColumnSelection columnSelection, JalviewLite applet,
+ HiddenColumns hidden, JalviewLite applet,
String title, boolean embedded, boolean addToDisplay)
{
if (applet != null)
{
viewport.hideSequence(hiddenSeqs);
}
- if (columnSelection != null)
+ if (hidden != null)
{
- viewport.setColumnSelection(columnSelection);
+ viewport.getAlignment().setHiddenColumns(hidden);
}
viewport.setScaleAboveWrapped(scaleAbove.getState());
{
copiedHiddenColumns = new Vector();
int hiddenOffset = viewport.getSelectionGroup().getStartRes();
- for (int[] region : viewport.getColumnSelection().getHiddenColumns())
+ for (int[] region : viewport.getAlignment().getHiddenColumns()
+ .getHiddenRegions())
{
copiedHiddenColumns.addElement(new int[] {
region[0] - hiddenOffset, region[1] - hiddenOffset });
boolean selected = conservationMenuItem.getState();
modifyConservation.setEnabled(selected);
viewport.setConservationSelected(selected);
-
- // viewport.setAbovePIDThreshold(false);
- // abovePIDThreshold.setState(false);
+ viewport.getResidueShading().setConservationApplied(selected);
changeColour(viewport.getGlobalColourScheme());
boolean selected = abovePIDThreshold.getState();
modifyPID.setEnabled(selected);
viewport.setAbovePIDThreshold(selected);
- // conservationMenuItem.setState(false);
- // viewport.setConservationSelected(false);
+ if (!selected)
+ {
+ viewport.getResidueShading().setThreshold(0,
+ viewport.isIgnoreGapsConsensus());
+ }
changeColour(viewport.getGlobalColourScheme());
{
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
AlignmentSorter.sortByPID(viewport.getAlignment(), viewport
- .getAlignment().getSequenceAt(0), null);
+ .getAlignment().getSequenceAt(0));
addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
viewport.getAlignment()));
public void averageDistanceTreeMenuItem_actionPerformed()
{
- NewTreePanel("AV", "PID", "Average distance tree using PID");
+ newTreePanel(TreeBuilder.AVERAGE_DISTANCE, new PIDModel().getName(),
+ "Average distance tree using PID");
}
public void neighbourTreeMenuItem_actionPerformed()
{
- NewTreePanel("NJ", "PID", "Neighbour joining tree using PID");
+ newTreePanel(TreeBuilder.NEIGHBOUR_JOINING, new PIDModel().getName(),
+ "Neighbour joining tree using PID");
}
protected void njTreeBlosumMenuItem_actionPerformed()
{
- NewTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
+ newTreePanel(TreeBuilder.NEIGHBOUR_JOINING, ScoreModels.getInstance()
+ .getBlosum62().getName(),
+ "Neighbour joining tree using BLOSUM62");
}
protected void avTreeBlosumMenuItem_actionPerformed()
{
- NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
+ newTreePanel(TreeBuilder.AVERAGE_DISTANCE, ScoreModels.getInstance()
+ .getBlosum62().getName(),
+ "Average distance tree using BLOSUM62");
}
- void NewTreePanel(String type, String pwType, String title)
+ void newTreePanel(String type, String pwType, String title)
{
// are the sequences aligned?
if (!viewport.getAlignment().isAligned(false))
* @param csel
* - columns to be selected on the alignment
*/
- public void select(SequenceGroup sel, ColumnSelection csel)
+ public void select(SequenceGroup sel, ColumnSelection csel,
+ HiddenColumns hidden)
{
- alignPanel.seqPanel.selection(sel, csel, null);
+ alignPanel.seqPanel.selection(sel, csel, hidden, null);
}
public void scrollTo(int row, int column)
*/
package jalview.appletgui;
-import jalview.analysis.NJTree;
+import jalview.analysis.TreeModel;
import jalview.api.AlignViewportI;
import jalview.api.FeatureSettingsModelI;
import jalview.bin.JalviewLite;
import jalview.commands.CommandI;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.Sequence;
import jalview.structure.StructureSelectionManager;
import jalview.structure.VamsasSource;
import jalview.viewmodel.AlignmentViewport;
-import jalview.viewmodel.ViewportRanges;
import java.awt.Font;
+import java.awt.FontMetrics;
public class AlignViewport extends AlignmentViewport implements
SelectionSource
boolean validCharWidth = true;
- NJTree currentTree = null;
+ TreeModel currentTree = null;
public jalview.bin.JalviewLite applet;
public AlignViewport(AlignmentI al, JalviewLite applet)
{
- super();
+ super(al);
calculator = new jalview.workers.AlignCalcManager();
this.applet = applet;
- alignment = al;
- ranges = new ViewportRanges(this.alignment);
+
// we always pad gaps
this.setPadGaps(true);
}
}
}
- setFont(font);
+ setFont(font, true);
MAC = new jalview.util.Platform().isAMac();
showConsensus = applet.getDefaultParameter("showConsensus",
showConsensus);
+ showOccupancy = applet.getDefaultParameter("showOccupancy",
+ showOccupancy);
+
setShowUnconserved(applet.getDefaultParameter("showUnconserved",
getShowUnconserved()));
private float heightScale = 1, widthScale = 1;
- public void setFont(Font f)
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setFont(Font f, boolean setGrid)
{
font = f;
if (nullFrame == null)
nullFrame.addNotify();
}
- java.awt.FontMetrics fm = nullFrame.getGraphics().getFontMetrics(font);
- setCharHeight((int) (heightScale * fm.getHeight()));
- setCharWidth((int) (widthScale * fm.charWidth('M')));
+ if (setGrid)
+ {
+ FontMetrics fm = nullFrame.getGraphics().getFontMetrics(font);
+ setCharHeight((int) (heightScale * fm.getHeight()));
+ setCharWidth((int) (widthScale * fm.charWidth('M')));
+ }
if (isUpperCasebold())
{
Font f2 = new Font(f.getName(), Font.BOLD, f.getSize());
- fm = nullFrame.getGraphics().getFontMetrics(f2);
+ FontMetrics fm = nullFrame.getGraphics().getFontMetrics(f2);
setCharWidth((int) (widthScale * (fm.stringWidth("MMMMMMMMMMM") / 10)));
}
}
ranges.setEndSeq(height / getCharHeight());
}
- public void setCurrentTree(NJTree tree)
+ public void setCurrentTree(TreeModel tree)
{
currentTree = tree;
}
- public NJTree getCurrentTree()
+ public TreeModel getCurrentTree()
{
return currentTree;
}
{
getStructureSelectionManager().sendSelection(
new SequenceGroup(getSelectionGroup()),
- new ColumnSelection(getColumnSelection()), this);
+ new ColumnSelection(getColumnSelection()),
+ new HiddenColumns(getAlignment().getHiddenColumns()), this);
}
/**
int start = -1;
if (av.hasHiddenColumns())
{
- start = av.getColumnSelection().findColumnPosition(ostart);
- end = av.getColumnSelection().findColumnPosition(end);
+ AlignmentI al = av.getAlignment();
+ start = al.getHiddenColumns().findColumnPosition(ostart);
+ end = al.getHiddenColumns().findColumnPosition(end);
if (start == end)
{
- if (!scrollToNearest && !av.getColumnSelection().isVisible(ostart))
+ if (!scrollToNearest && !al.getHiddenColumns().isVisible(ostart))
{
// don't scroll - position isn't visible
return false;
if (av.hasHiddenColumns())
{
- width = av.getColumnSelection().findColumnPosition(width);
+ width = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(width);
}
if (x < 0)
{
if ((hextent + x) > width)
{
- System.err.println("hextent was " + hextent + " and x was " + x);
-
+ // System.err.println("hextent was " + hextent + " and x was " + x);
+ //
x = width - hextent;
}
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
int canvasWidth = seqPanel.seqCanvas
package jalview.appletgui;
import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.schemes.AnnotationColourGradient;
import jalview.util.MessageManager;
import jalview.viewmodel.annotationfilter.AnnotationFilterParameter;
private int actionOption = ACTION_OPTION_SELECT;
- private ColumnSelection oldColumnSelection;
+ private HiddenColumns oldHiddenColumns;
public AnnotationColumnChooser()
{
{
return;
}
- setOldColumnSelection(av.getColumnSelection());
+ setOldHiddenColumns(av.getAlignment().getHiddenColumns());
adjusting = true;
Vector<String> list = new Vector<String>();
int index = 1;
}
populateThresholdComboBox(threshold);
-
+ AnnotationColumnChooser lastChooser = av
+ .getAnnotationColumnSelectionState();
// restore Object state from the previous session if one exists
- if (av.getAnnotationColumnSelectionState() != null)
+ if (lastChooser != null)
{
- currentSearchPanel = av.getAnnotationColumnSelectionState()
+ currentSearchPanel = lastChooser
.getCurrentSearchPanel();
- currentStructureFilterPanel = av.getAnnotationColumnSelectionState()
+ currentStructureFilterPanel = lastChooser
.getCurrentStructureFilterPanel();
- annotations.select(av.getAnnotationColumnSelectionState()
+ annotations.select(lastChooser
.getAnnotations().getSelectedIndex());
- threshold.select(av.getAnnotationColumnSelectionState()
+ threshold.select(lastChooser
.getThreshold().getSelectedIndex());
- actionOption = av.getAnnotationColumnSelectionState()
+ actionOption = lastChooser
.getActionOption();
+ percentThreshold.setState(lastChooser.percentThreshold.getState());
}
try
thresholdValue.setEnabled(false);
thresholdValue.setColumns(7);
+ thresholdValue.setCaretPosition(0);
ok.addActionListener(this);
cancel.addActionListener(this);
// thresholdPanel.setFont(JvSwingUtils.getLabelFont());
// thresholdPanel.setLayout(new MigLayout("", "[left][right]", "[][]"));
+ percentThreshold.setLabel("As percentage");
+ percentThreshold.addItemListener(this);
+
actionPanel.setBackground(Color.white);
// actionPanel.setFont(JvSwingUtils.getLabelFont());
thresholdPanel.add(getThreshold());
thresholdPanel.add(slider);
thresholdPanel.add(thresholdValue);
+ thresholdPanel.add(percentThreshold);
actionPanel.add(ok);
actionPanel.add(cancel);
@SuppressWarnings("unchecked")
public void reset()
{
- if (this.getOldColumnSelection() != null)
+ if (this.getOldHiddenColumns() != null)
{
av.getColumnSelection().clear();
if (av.getAnnotationColumnSelectionState() != null)
{
- ColumnSelection oldSelection = av
+ HiddenColumns oldHidden = av
.getAnnotationColumnSelectionState()
- .getOldColumnSelection();
- if (oldSelection != null && oldSelection.getHiddenColumns() != null
- && !oldSelection.getHiddenColumns().isEmpty())
+ .getOldHiddenColumns();
+ if (oldHidden != null && oldHidden.getHiddenRegions() != null
+ && !oldHidden.getHiddenRegions().isEmpty())
{
- for (Iterator<int[]> itr = oldSelection.getHiddenColumns()
+ for (Iterator<int[]> itr = oldHidden.getHiddenRegions()
.iterator(); itr.hasNext();)
{
int positions[] = itr.next();
av.hideColumns(positions[0], positions[1]);
}
}
- av.setColumnSelection(oldSelection);
+ av.getAlignment().setHiddenColumns(oldHidden);
}
ap.paintAlignment(true);
}
{
if (!adjusting)
{
- thresholdValue.setText((slider.getValue() / 1000f) + "");
+ setThresholdValueText();
valueChanged(!sliderDragging);
}
}
slider.setEnabled(true);
thresholdValue.setEnabled(true);
+ percentThreshold.setEnabled(true);
if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD)
{
slider.setEnabled(false);
thresholdValue.setEnabled(false);
thresholdValue.setText("");
+ percentThreshold.setEnabled(false);
// build filter params
}
else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD)
slider.setMinimum((int) (getCurrentAnnotation().graphMin * 1000));
slider.setMaximum((int) (getCurrentAnnotation().graphMax * 1000));
slider.setValue((int) (getCurrentAnnotation().threshold.value * 1000));
- thresholdValue.setText(getCurrentAnnotation().threshold.value + "");
+ setThresholdValueText();
// slider.setMajorTickSpacing((int) (range / 10f));
slider.setEnabled(true);
thresholdValue.setEnabled(true);
+ percentThreshold.setEnabled(true);
adjusting = false;
// build filter params
filterParams
.setThresholdType(AnnotationFilterParameter.ThresholdType.NO_THRESHOLD);
- if (getCurrentAnnotation().graph != AlignmentAnnotation.NO_GRAPH)
+ if (getCurrentAnnotation().isQuantitative())
{
filterParams
.setThresholdValue(getCurrentAnnotation().threshold.value);
ap.paintAlignment(true);
}
- public ColumnSelection getOldColumnSelection()
+ public HiddenColumns getOldHiddenColumns()
{
- return oldColumnSelection;
+ return oldHiddenColumns;
}
- public void setOldColumnSelection(ColumnSelection currentColumnSelection)
+ public void setOldHiddenColumns(HiddenColumns currentHiddenColumns)
{
- if (currentColumnSelection != null)
+ if (currentHiddenColumns != null)
{
- this.oldColumnSelection = new ColumnSelection(currentColumnSelection);
+ this.oldHiddenColumns = new HiddenColumns(currentHiddenColumns);
}
}
{
threshold_actionPerformed(null);
}
+ else if (e.getSource() == percentThreshold)
+ {
+ if (!adjusting)
+ {
+ percentageValue_actionPerformed();
+ }
+
+ }
}
public void selectedAnnotationChanged()
{
String currentView = AnnotationColumnChooser.NO_GRAPH_VIEW;
if (av.getAlignment().getAlignmentAnnotation()[getAnnotations()
- .getSelectedIndex()].graph != AlignmentAnnotation.NO_GRAPH)
+ .getSelectedIndex()].isQuantitative())
{
currentView = AnnotationColumnChooser.GRAPH_VIEW;
}
@Override
public void actionPerformed(ActionEvent evt)
{
- if (evt.getSource() == thresholdValue)
- {
- try
- {
- float f = new Float(thresholdValue.getText()).floatValue();
- slider.setValue((int) (f * 1000));
- adjustmentValueChanged(null);
- } catch (NumberFormatException ex)
- {
- }
- }
- else if (evt.getSource() == ok)
+ if (evt.getSource() == ok)
{
ok_actionPerformed(null);
}
if (av.hasHiddenColumns())
{
jalview.appletgui.AlignFrame.copiedHiddenColumns = new Vector();
- for (int[] region : av.getColumnSelection().getHiddenColumns())
+ for (int[] region : av.getAlignment().getHiddenColumns()
+ .getHiddenRegions())
{
jalview.appletgui.AlignFrame.copiedHiddenColumns
.addElement(new int[] { region[0], region[1] });
{
for (int index : av.getColumnSelection().getSelected())
{
- if (av.getColumnSelection().isVisible(index))
+ if (av.getAlignment().getHiddenColumns().isVisible(index))
{
anot[index] = null;
}
{
// TODO: JAL-2001 - provide a fast method to list visible selected
// columns
- if (!av.getColumnSelection().isVisible(index))
+ if (!av.getAlignment().getHiddenColumns().isVisible(index))
{
continue;
}
for (int index : av.getColumnSelection().getSelected())
{
- if (!av.getColumnSelection().isVisible(index))
+ if (!av.getAlignment().getHiddenColumns().isVisible(index))
{
continue;
}
for (int index : av.getColumnSelection().getSelected())
{
- if (!av.getColumnSelection().isVisible(index))
+ if (!av.getAlignment().getHiddenColumns().isVisible(index))
{
continue;
}
if (av.hasHiddenColumns())
{
- column = av.getColumnSelection().adjustForHiddenColumns(column);
+ column = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(column);
}
if (row > -1 && column < aa[row].annotations.length
import java.awt.Scrollbar;
import java.awt.TextField;
import java.awt.event.ActionEvent;
-import java.util.Vector;
@SuppressWarnings("serial")
public abstract class AnnotationRowFilter extends Panel
protected Scrollbar slider = new Scrollbar(Scrollbar.HORIZONTAL);
+ protected Checkbox percentThreshold = new Checkbox();
+
protected TextField thresholdValue = new TextField(20);
protected Frame frame;
updateView();
}
+ /**
+ * update the text field from the threshold slider. preserves state of
+ * 'adjusting' so safe to call in init.
+ */
+ protected void setThresholdValueText()
+ {
+ boolean oldadj = adjusting;
+ adjusting = true;
+ if (percentThreshold.getState())
+ {
+ double scl = slider.getMaximum() - slider.getMinimum();
+ scl = (slider.getValue() - slider.getMinimum()) / scl;
+ thresholdValue.setText(100f * scl + "");
+ }
+ else
+ {
+ thresholdValue.setText((slider.getValue() / 1000f) + "");
+ }
+ thresholdValue.setCaretPosition(0);
+ adjusting = oldadj;
+ }
+
public void thresholdValue_actionPerformed(ActionEvent e)
{
try
{
float f = Float.parseFloat(thresholdValue.getText());
- slider.setValue((int) (f * 1000));
- updateView();
+ if (percentThreshold.getState())
+ {
+ int pos = slider.getMinimum()
+ + (int) ((slider.getMaximum() - slider.getMinimum()) * f / 100f);
+ slider.setValue(pos);
+ }
+ else
+ {
+ slider.setValue((int) (f * 1000));
+ }
+ valueChanged(false);
} catch (NumberFormatException ex)
{
}
}
+ protected void percentageValue_actionPerformed()
+ {
+ setThresholdValueText();
+ }
+
protected void populateThresholdComboBox(Choice threshold)
{
threshold.addItem(MessageManager
import jalview.api.FeaturesSourceI;
import jalview.bin.JalviewLite;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.io.AlignmentFileReaderI;
if (source instanceof ComplexAlignFile)
{
- ColumnSelection colSel = ((ComplexAlignFile) source)
- .getColumnSelection();
+ HiddenColumns colSel = ((ComplexAlignFile) source)
+ .getHiddenColumns();
SequenceI[] hiddenSeqs = ((ComplexAlignFile) source)
.getHiddenSequences();
boolean showSeqFeatures = ((ComplexAlignFile) source)
import java.awt.Choice;
import java.awt.Color;
import java.awt.Dimension;
+import java.awt.FlowLayout;
import java.awt.Font;
+import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.awt.event.TextEvent;
+import java.awt.event.TextListener;
import java.util.Hashtable;
/**
public class FeatureRenderer extends
jalview.renderer.seqfeatures.FeatureRenderer
{
+ /*
+ * creating a new feature defaults to the type and group as
+ * the last one created
+ */
+ static String lastFeatureAdded = "feature_1";
+
+ static String lastFeatureGroupAdded = "Jalview";
// Holds web links for feature groups and feature types
// in the form label|link
}
- static String lastFeatureAdded;
-
- static String lastFeatureGroupAdded;
-
- static String lastDescriptionAdded;
-
int featureIndex = 0;
boolean deleteFeature = false;
}
+ /**
+ * Shows a dialog allowing the user to create, or amend or delete, sequence
+ * features. If null in the supplied feature(s), feature type and group
+ * default to those for the last feature created (with initial defaults of
+ * "feature_1" and "Jalview").
+ *
+ * @param sequences
+ * @param features
+ * @param create
+ * @param ap
+ * @return
+ */
boolean amendFeatures(final SequenceI[] sequences,
- final SequenceFeature[] features, boolean newFeatures,
+ final SequenceFeature[] features, boolean create,
final AlignmentPanel ap)
{
- Panel bigPanel = new Panel(new BorderLayout());
+ final Panel bigPanel = new Panel(new BorderLayout());
final TextField name = new TextField(16);
- final TextField source = new TextField(16);
+ final TextField group = new TextField(16);
final TextArea description = new TextArea(3, 35);
final TextField start = new TextField(8);
final TextField end = new TextField(8);
Button deleteButton = new Button("Delete");
deleteFeature = false;
+ name.addTextListener(new TextListener()
+ {
+ @Override
+ public void textValueChanged(TextEvent e)
+ {
+ warnIfTypeHidden(ap.alignFrame, name.getText());
+ }
+ });
+ group.addTextListener(new TextListener()
+ {
+ @Override
+ public void textValueChanged(TextEvent e)
+ {
+ warnIfGroupHidden(ap.alignFrame, group.getText());
+ }
+ });
colourPanel = new FeatureColourPanel();
colourPanel.setSize(110, 15);
final FeatureRenderer fr = this;
// /////////////////////////////////////
// /MULTIPLE FEATURES AT SELECTED RESIDUE
- if (!newFeatures && features.length > 1)
+ if (!create && features.length > 1)
{
panel = new Panel(new GridLayout(4, 1));
tmp = new Panel();
featureIndex = index;
name.setText(features[index].getType());
description.setText(features[index].getDescription());
- source.setText(features[index].getFeatureGroup());
+ group.setText(features[index].getFeatureGroup());
start.setText(features[index].getBegin() + "");
end.setText(features[index].getEnd() + "");
tmp = new Panel();
panel.add(tmp);
tmp.add(new Label(MessageManager.getString("label.group:"), Label.RIGHT));
- tmp.add(source);
+ tmp.add(group);
tmp = new Panel();
panel.add(tmp);
Label.RIGHT));
panel.add(new ScrollPane().add(description));
- if (!newFeatures)
+ if (!create)
{
bigPanel.add(panel, BorderLayout.SOUTH);
bigPanel.add(panel, BorderLayout.CENTER);
}
- if (lastFeatureAdded == null)
- {
- if (features[0].type != null)
- {
- lastFeatureAdded = features[0].type;
- }
- else
- {
- lastFeatureAdded = "feature_1";
- }
- }
-
- if (lastFeatureGroupAdded == null)
- {
- if (features[0].featureGroup != null)
- {
- lastFeatureGroupAdded = features[0].featureGroup;
- }
- else
- {
- lastFeatureAdded = "Jalview";
- }
- }
+ /*
+ * use defaults for type and group (and update them on Confirm) only
+ * if feature type has not been supplied by the caller
+ * (e.g. for Amend, or create features from Find)
+ */
+ boolean useLastDefaults = features[0].getType() == null;
+ String featureType = useLastDefaults ? lastFeatureAdded : features[0]
+ .getType();
+ String featureGroup = useLastDefaults ? lastFeatureGroupAdded
+ : features[0].getFeatureGroup();
- String title = newFeatures ? MessageManager
+ String title = create ? MessageManager
.getString("label.create_new_sequence_features")
: MessageManager.formatMessage("label.amend_delete_features",
new String[] { sequences[0].getName() });
dialog.setMainPanel(bigPanel);
- if (newFeatures)
- {
- name.setText(lastFeatureAdded);
- source.setText(lastFeatureGroupAdded);
- }
- else
+ name.setText(featureType);
+ group.setText(featureGroup);
+
+ if (!create)
{
dialog.ok.setLabel(MessageManager.getString("label.amend"));
dialog.buttonPanel.add(deleteButton, 1);
dialog.setVisible(false);
}
});
- name.setText(features[0].getType());
- source.setText(features[0].getFeatureGroup());
}
start.setText(features[0].getBegin() + "");
FeaturesFile ffile = new FeaturesFile();
- if (dialog.accept)
- {
- lastFeatureAdded = name.getText().trim();
- lastFeatureGroupAdded = source.getText().trim();
- lastDescriptionAdded = description.getText().replace('\n', ' ');
- }
-
- if (lastFeatureGroupAdded != null && lastFeatureGroupAdded.length() < 1)
+ /*
+ * only update default type and group if we used defaults
+ */
+ String enteredType = name.getText().trim();
+ if (dialog.accept && useLastDefaults)
{
- lastFeatureGroupAdded = null;
+ lastFeatureAdded = enteredType;
+ lastFeatureGroupAdded = group.getText().trim();
}
- if (!newFeatures)
+ if (!create)
{
-
SequenceFeature sf = features[featureIndex];
if (dialog.accept)
{
- sf.type = lastFeatureAdded;
- sf.featureGroup = lastFeatureGroupAdded;
- sf.description = lastDescriptionAdded;
+ sf.type = enteredType;
+ sf.featureGroup = group.getText().trim();
+ if (sf.featureGroup != null && sf.featureGroup.length() < 1)
+ {
+ sf.featureGroup = null;
+ }
+ sf.description = description.getText().replace('\n', ' ');
if (!colourPanel.isGcol)
{
// update colour - otherwise its already done.
sf.end = Integer.parseInt(end.getText());
} catch (NumberFormatException ex)
{
+ //
}
+ boolean typeOrGroupChanged = (!featureType.equals(sf.type) || !featureGroup
+ .equals(sf.featureGroup));
ffile.parseDescriptionHTML(sf, false);
- setVisible(lastFeatureAdded); // if user edited name then make sure new
- // type is visible
+ if (typeOrGroupChanged)
+ {
+ featuresAdded();
+ }
}
if (deleteFeature)
{
sequences[0].deleteFeature(sf);
+ // ensure Feature Settings reflects removal of feature / group
+ featuresAdded();
}
-
}
else
{
+ /*
+ * adding feature(s)
+ */
if (dialog.accept && name.getText().length() > 0)
{
for (int i = 0; i < sequences.length; i++)
{
- features[i].type = lastFeatureAdded;
- features[i].featureGroup = lastFeatureGroupAdded;
- features[i].description = lastDescriptionAdded;
+ features[i].type = enteredType;
+ features[i].featureGroup = group.getText().trim();
+ features[i].description = description.getText()
+ .replace('\n', ' ');
sequences[i].addSequenceFeature(features[i]);
ffile.parseDescriptionHTML(features[i], false);
}
Color newColour = colourPanel.getBackground();
// setColour(lastFeatureAdded, fcol);
- if (lastFeatureGroupAdded != null)
- {
- setGroupVisibility(lastFeatureGroupAdded, true);
- }
- setColour(lastFeatureAdded, new FeatureColour(newColour)); // was fcol
- setVisible(lastFeatureAdded);
- findAllFeatures(false); // different to original applet behaviour ?
- // findAllFeatures();
+ setColour(enteredType, new FeatureColour(newColour)); // was fcol
+ featuresAdded();
}
else
{
return true;
}
+
+ protected void warnIfGroupHidden(Frame frame, String group)
+ {
+ if (featureGroups.containsKey(group) && !featureGroups.get(group))
+ {
+ String msg = MessageManager.formatMessage("label.warning_hidden",
+ MessageManager.getString("label.group"), group);
+ showWarning(frame, msg);
+ }
+ }
+
+ protected void warnIfTypeHidden(Frame frame, String type)
+ {
+ if (getRenderOrder().contains(type))
+ {
+ if (!showFeatureOfType(type))
+ {
+ String msg = MessageManager.formatMessage("label.warning_hidden",
+ MessageManager.getString("label.feature_type"), type);
+ showWarning(frame, msg);
+ }
+ }
+ }
+
+ /**
+ * @param frame
+ * @param msg
+ */
+ protected void showWarning(Frame frame, String msg)
+ {
+ JVDialog d = new JVDialog(frame, "", true, 350, 200);
+ Panel mp = new Panel();
+ d.ok.setLabel(MessageManager.getString("action.ok"));
+ d.cancel.setVisible(false);
+ mp.setLayout(new FlowLayout());
+ mp.add(new Label(msg));
+ d.setMainPanel(mp);
+ d.setVisible(true);
+ }
}
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.Vector;
public class FeatureSettings extends Panel implements ItemListener,
{
fr.findAllFeatures(true); // was default - now true to make all visible
}
+ groupPanel = new Panel();
discoverAllFeatureData();
add(lowerPanel, BorderLayout.SOUTH);
- if (groupPanel != null)
- {
- groupPanel.setLayout(new GridLayout(
- (fr.getFeatureGroupsSize()) / 4 + 1, 4)); // JBPNote - this was
- // scaled on number of
- // visible groups. seems
- // broken
- groupPanel.validate();
+ groupPanel.setLayout(new GridLayout(
+ (fr.getFeatureGroupsSize()) / 4 + 1, 4)); // JBPNote - this was
+ // scaled on number of
+ // visible groups. seems
+ // broken
+ groupPanel.validate();
+
+ add(groupPanel, BorderLayout.NORTH);
- add(groupPanel, BorderLayout.NORTH);
- }
frame = new Frame();
frame.add(this);
final FeatureSettings me = this;
if (fr.getAllFeatureColours() != null
&& fr.getAllFeatureColours().size() > 0)
{
- rebuildGroups();
+ // rebuildGroups();
}
resetTable(false);
}
/**
- * rebuilds the group panel
+ * Answers the visibility of the given group, and adds a checkbox for it if
+ * there is not one already
*/
- public void rebuildGroups()
+ public boolean checkGroupState(String group)
{
- boolean rdrw = false;
- if (groupPanel == null)
- {
- groupPanel = new Panel();
- }
- else
- {
- rdrw = true;
- groupPanel.removeAll();
- }
- // TODO: JAL-964 - smoothly incorporate new group entries if panel already
- // displayed and new groups present
- for (String group : fr.getFeatureGroups())
- {
- boolean vis = fr.checkGroupVisibility(group, false);
- Checkbox check = new MyCheckbox(group, vis, false);
- check.addMouseListener(this);
- check.setFont(new Font("Serif", Font.BOLD, 12));
- check.addItemListener(groupItemListener);
- // note - visibility seems to correlate with displayed. ???wtf ??
- check.setVisible(vis);
- groupPanel.add(check);
- }
- if (rdrw)
+ boolean visible = fr.checkGroupVisibility(group, true);
+
+ /*
+ * is there already a checkbox for this group?
+ */
+ for (int g = 0; g < groupPanel.getComponentCount(); g++)
{
- groupPanel.validate();
+ if (((Checkbox) groupPanel.getComponent(g)).getLabel().equals(group))
+ {
+ ((Checkbox) groupPanel.getComponent(g)).setState(visible);
+ return visible;
+ }
}
+
+ /*
+ * add a new checkbox
+ */
+ Checkbox check = new MyCheckbox(group, visible, false);
+ check.addMouseListener(this);
+ check.setFont(new Font("Serif", Font.BOLD, 12));
+ check.addItemListener(groupItemListener);
+ groupPanel.add(check);
+
+ groupPanel.validate();
+ return visible;
}
// This routine adds and removes checkboxes depending on
SequenceFeature[] tmpfeatures;
String group = null, type;
Vector<String> visibleChecks = new Vector<String>();
+ Set<String> foundGroups = new HashSet<String>();
AlignmentI alignment = av.getAlignment();
+
for (int i = 0; i < alignment.getHeight(); i++)
{
if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
while (index < tmpfeatures.length)
{
group = tmpfeatures[index].featureGroup;
+ foundGroups.add(group);
- if (group == null || fr.checkGroupVisibility(group, true))
+ if (group == null || checkGroupState(group))
{
type = tmpfeatures[index].getType();
if (!visibleChecks.contains(type))
}
}
+ /*
+ * remove any checkboxes for groups not present
+ */
+ pruneGroups(foundGroups);
+
Component[] comps;
int cSize = featurePanel.getComponentCount();
MyCheckbox check;
}
/**
+ * Remove from the groups panel any checkboxes for groups that are not in the
+ * foundGroups set. This enables removing a group from the display when the
+ * last feature in that group is deleted.
+ *
+ * @param foundGroups
+ */
+ protected void pruneGroups(Set<String> foundGroups)
+ {
+ for (int g = 0; g < groupPanel.getComponentCount(); g++)
+ {
+ Checkbox checkbox = (Checkbox) groupPanel.getComponent(g);
+ if (!foundGroups.contains(checkbox.getLabel()))
+ {
+ groupPanel.remove(checkbox);
+ }
+ }
+ }
+
+ /**
* update the checklist of feature types with the given type
*
* @param groupsChanged
SequenceI[] seqs = new SequenceI[searchResults.getSize()];
SequenceFeature[] features = new SequenceFeature[searchResults
.getSize()];
+ String searchString = textfield.getText().trim();
int i = 0;
for (SearchResultMatchI match : searchResults.getResults())
{
seqs[i] = match.getSequence().getDatasetSequence();
- features[i] = new SequenceFeature(textfield.getText().trim(),
+ features[i] = new SequenceFeature(searchString,
"Search Results", null, match.getStart(), match.getEnd(),
"Search Results");
i++;
*/
package jalview.appletgui;
-import jalview.api.ViewStyleI;
import jalview.util.MessageManager;
import java.awt.BorderLayout;
private Checkbox scaleAsCdna = new Checkbox();
+ private Checkbox fontAsCdna = new Checkbox();
+
private Button ok = new Button();
private Button cancel = new Button();
private Font oldFont;
+ private Font oldComplementFont;
+
private int oldCharWidth = 0;
+ /*
+ * the state of 'scale protein to cDNA' on opening the dialog
+ */
private boolean oldScaleProtein = false;
+ /*
+ * the state of 'same font for protein and cDNA' on opening the dialog
+ */
+ boolean oldMirrorFont;
+
private Font lastSelected = null;
private int lastSelStyle = 0;
private Frame frame;
+ boolean inSplitFrame = false;
+
/**
* Constructor for a TreePanel font chooser
*
{
this.ap = ap;
oldFont = ap.av.getFont();
- oldCharWidth = ap.av.getViewStyle().getCharWidth();
- oldScaleProtein = ap.av.getViewStyle().isScaleProteinAsCdna();
+ oldCharWidth = ap.av.getCharWidth();
+ oldScaleProtein = ap.av.isScaleProteinAsCdna();
+ oldMirrorFont = ap.av.isProteinFontAsCdna();
try
{
this.frame = new Frame();
frame.add(this);
jalview.bin.JalviewLite.addFrame(frame,
- MessageManager.getString("action.change_font"), 440, 115);
+ MessageManager.getString("action.change_font"), 440, 145);
init = false;
}
/**
* Actions on change of font name, size or style.
*/
+ @Override
public void itemStateChanged(ItemEvent evt)
{
final Object source = evt.getSource();
{
scaleAsCdna_actionPerformed();
}
+ else if (source == fontAsCdna)
+ {
+ mirrorFont_actionPerformed();
+ }
+ }
+
+ /**
+ * Action on checking or unchecking 'use same font across split screen'
+ * option. When checked, the font settings are copied to the other half of the
+ * split screen. When unchecked, the other half is restored to its initial
+ * settings.
+ */
+ protected void mirrorFont_actionPerformed()
+ {
+ boolean selected = fontAsCdna.getState();
+ ap.av.setProteinFontAsCdna(selected);
+ ap.av.getCodingComplement().setProteinFontAsCdna(selected);
+
+ if (!selected)
+ {
+ ap.av.getCodingComplement().setFont(oldComplementFont, true);
+ }
+ changeFont();
}
/**
if (ap != null)
{
ap.av.setScaleProteinAsCdna(oldScaleProtein);
+ ap.av.setProteinFontAsCdna(oldMirrorFont);
+
if (ap.av.getCodingComplement() != null)
{
ap.av.getCodingComplement().setScaleProteinAsCdna(oldScaleProtein);
- ap.alignFrame.getSplitFrame().repaint();
+ ap.av.getCodingComplement().setProteinFontAsCdna(oldMirrorFont);
+ ap.av.getCodingComplement().setFont(oldComplementFont, true);
+ SplitFrame splitFrame = ap.alignFrame.getSplitFrame();
+ splitFrame.adjustLayout();
+ splitFrame.getComplement(ap.alignFrame).alignPanel.fontChanged();
+ splitFrame.repaint();
}
- ap.av.setFont(oldFont);
- ViewStyleI style = ap.av.getViewStyle();
- if (style.getCharWidth() != oldCharWidth)
+ ap.av.setFont(oldFont, true);
+ if (ap.av.getCharWidth() != oldCharWidth)
{
- style.setCharWidth(oldCharWidth);
- ap.av.setViewStyle(style);
+ ap.av.setCharWidth(oldCharWidth);
}
ap.paintAlignment(true);
}
}
else if (ap != null)
{
- ap.av.setFont(newFont);
+ ap.av.setFont(newFont, true);
ap.fontChanged();
+
+ /*
+ * and change font in other half of split frame if any
+ */
+ if (inSplitFrame)
+ {
+ if (fontAsCdna.getState())
+ {
+ ap.av.getCodingComplement().setFont(newFont, true);
+ }
+ SplitFrame splitFrame = ap.alignFrame.getSplitFrame();
+ splitFrame.adjustLayout();
+ splitFrame.getComplement(ap.alignFrame).alignPanel.fontChanged();
+ splitFrame.repaint();
+ }
}
// remember last selected
lastSelected = newFont;
scaleAsCdna.addItemListener(this);
scaleAsCdna.setState(ap.av.isScaleProteinAsCdna());
+ fontAsCdna.setLabel(MessageManager.getString("label.font_as_cdna"));
+ fontAsCdna.setFont(VERDANA_11PT);
+ fontAsCdna.addItemListener(this);
+ fontAsCdna.setState(ap.av.isProteinFontAsCdna());
+
ok.setFont(VERDANA_11PT);
ok.setLabel(MessageManager.getString("action.ok"));
ok.addActionListener(new ActionListener()
stylePanel.add(fontStyle, BorderLayout.CENTER);
sizePanel.add(sizeLabel, BorderLayout.WEST);
sizePanel.add(fontSize, BorderLayout.CENTER);
- scalePanel.add(scaleAsCdna, BorderLayout.CENTER);
+ scalePanel.add(scaleAsCdna, BorderLayout.NORTH);
+ scalePanel.add(fontAsCdna, BorderLayout.SOUTH);
okCancelPanel.add(ok, null);
okCancelPanel.add(cancel, null);
this.add(optionsPanel, BorderLayout.NORTH);
if (ap.alignFrame.getSplitFrame() != null)
{
+ inSplitFrame = true;
+ oldComplementFont = ((AlignViewport) ap.av.getCodingComplement())
+ .getFont();
this.add(scalePanel, BorderLayout.CENTER);
}
this.add(okCancelPanel, BorderLayout.SOUTH);
ap.av.setScaleProteinAsCdna(scaleAsCdna.getState());
ap.av.getCodingComplement().setScaleProteinAsCdna(
scaleAsCdna.getState());
- ap.alignFrame.getSplitFrame().adjustLayout();
- ap.paintAlignment(true);
- ap.alignFrame.getSplitFrame().repaint();
+ changeFont();
}
}
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
int annotationHeight = 0;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
String id = sq.getName();
// get the default url with the sequence details filled in
+ if (urlProvider == null)
+ {
+ return;
+ }
String url = urlProvider.getPrimaryUrl(id);
String target = urlProvider.getPrimaryTarget(id);
try
// build a new links menu based on the current links + any non-positional
// features
- List<String> nlinks = urlProvider.getLinksForMenu();
-
+ List<String> nlinks;
+ if (urlProvider != null)
+ {
+ nlinks = urlProvider.getLinksForMenu();
+ }
+ else
+ {
+ nlinks = new ArrayList<String>();
+ }
SequenceFeature sf[] = sq == null ? null : sq.getSequenceFeatures();
for (int sl = 0; sf != null && sl < sf.length; sl++)
{
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.appletgui;
+
+import jalview.renderer.OverviewRenderer;
+import jalview.viewmodel.OverviewDimensions;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Image;
+
+public class OverviewCanvas extends Component
+{
+ // This is set true if the alignment view changes whilst
+ // the overview is being calculated
+ private volatile boolean restart = false;
+
+ private volatile boolean updaterunning = false;
+
+ private OverviewDimensions od;
+
+ private Image miniMe;
+
+ private Image offscreen;
+
+ private AlignViewport av;
+
+ // Can set different properties in this seqCanvas than
+ // main visible SeqCanvas
+ private SequenceRenderer sr;
+
+ private jalview.renderer.seqfeatures.FeatureRenderer fr;
+
+ private Frame nullFrame;
+
+ public OverviewCanvas(OverviewDimensions overviewDims,
+ AlignViewport alignvp)
+ {
+ od = overviewDims;
+ av = alignvp;
+
+ nullFrame = new Frame();
+ nullFrame.addNotify();
+
+ sr = new SequenceRenderer(av);
+ sr.graphics = nullFrame.getGraphics();
+ sr.renderGaps = false;
+ sr.forOverview = true;
+ fr = new jalview.renderer.seqfeatures.FeatureRenderer(av);
+ }
+
+ /**
+ * Update the overview dimensions object used by the canvas (e.g. if we change
+ * from showing hidden columns to hiding them or vice versa)
+ *
+ * @param overviewDims
+ */
+ public void resetOviewDims(OverviewDimensions overviewDims)
+ {
+ od = overviewDims;
+ }
+
+ /**
+ * Signals to drawing code that the associated alignment viewport has changed
+ * and a redraw will be required
+ */
+ public boolean restartDraw()
+ {
+ synchronized (this)
+ {
+ if (updaterunning)
+ {
+ restart = true;
+ }
+ else
+ {
+ updaterunning = true;
+ }
+ return restart;
+ }
+ }
+
+ public void draw(boolean showSequenceFeatures, boolean showAnnotation,
+ FeatureRenderer transferRenderer)
+ {
+ miniMe = null;
+
+ if (showSequenceFeatures)
+ {
+ fr.transferSettings(transferRenderer);
+ }
+
+ setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
+
+ OverviewRenderer or = new OverviewRenderer(sr, fr, od);
+ miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
+ offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
+
+ miniMe = or.draw(od.getRows(av.getAlignment()),
+ od.getColumns(av.getAlignment()));
+
+ Graphics mg = miniMe.getGraphics();
+
+ // checks for conservation annotation to make sure overview works for DNA
+ // too
+ if (showAnnotation)
+ {
+ mg.translate(0, od.getSequencesHeight());
+ or.drawGraph(mg, av.getAlignmentConservationAnnotation(),
+ av.getCharWidth(), od.getGraphHeight(),
+ od.getColumns(av.getAlignment()));
+ mg.translate(0, -od.getSequencesHeight());
+ }
+ System.gc();
+
+ if (restart)
+ {
+ restart = false;
+ draw(showSequenceFeatures, showAnnotation, transferRenderer);
+ }
+ else
+ {
+ updaterunning = false;
+ }
+ }
+
+ @Override
+ public void update(Graphics g)
+ {
+ paint(g);
+ }
+
+ @Override
+ public void paint(Graphics g)
+ {
+ Graphics og = offscreen.getGraphics();
+ if (miniMe != null)
+ {
+ og.drawImage(miniMe, 0, 0, this);
+ og.setColor(Color.red);
+ od.drawBox(og);
+ g.drawImage(offscreen, 0, 0, this);
+ }
+ }
+
+}
*/
package jalview.appletgui;
-import jalview.datamodel.SequenceI;
-import jalview.renderer.seqfeatures.FeatureColourFinder;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
import jalview.viewmodel.OverviewDimensions;
+import jalview.viewmodel.OverviewDimensionsHideHidden;
+import jalview.viewmodel.OverviewDimensionsShowHidden;
-import java.awt.Color;
+import java.awt.BorderLayout;
+import java.awt.CheckboxMenuItem;
import java.awt.Dimension;
-import java.awt.Frame;
-import java.awt.Graphics;
-import java.awt.Image;
import java.awt.Panel;
+import java.awt.PopupMenu;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
{
private OverviewDimensions od;
- private Image miniMe;
-
- private Image offscreen;
+ private OverviewCanvas oviewCanvas;
private AlignViewport av;
private AlignmentPanel ap;
- private boolean resizing = false;
-
- // This is set true if the user resizes whilst
- // the overview is being calculated
- private boolean resizeAgain = false;
-
- // Can set different properties in this seqCanvas than
- // main visible SeqCanvas
- private SequenceRenderer sr;
+ private boolean showHidden = true;
- private FeatureRenderer fr;
-
- private Frame nullFrame;
+ private boolean updateRunning = false;
public OverviewPanel(AlignmentPanel alPanel)
{
this.av = alPanel.av;
this.ap = alPanel;
setLayout(null);
- nullFrame = new Frame();
- nullFrame.addNotify();
-
- sr = new SequenceRenderer(av);
- sr.graphics = nullFrame.getGraphics();
- sr.renderGaps = false;
- sr.forOverview = true;
- fr = new FeatureRenderer(av);
- od = new OverviewDimensions(av.getRanges(),
+ od = new OverviewDimensionsShowHidden(av.getRanges(),
(av.isShowAnnotation() && av.getSequenceConsensusHash() != null));
+ oviewCanvas = new OverviewCanvas(od, av);
+ setLayout(new BorderLayout());
+ add(oviewCanvas, BorderLayout.CENTER);
+
setSize(new Dimension(od.getWidth(), od.getHeight()));
addComponentListener(new ComponentAdapter()
{
@Override
public void mouseClicked(MouseEvent evt)
{
+ if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
+ {
+ showPopupMenu(evt);
+ }
}
@Override
private void mouseAction(MouseEvent evt)
{
- od.updateViewportFromMouse(evt.getX(), evt.getY(), av.getAlignment()
- .getHiddenSequences(), av.getColumnSelection(), av
- .getRanges());
- ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
- ap.paintAlignment(false);
+ if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
+ {
+ if (!Platform.isAMac())
+ {
+ showPopupMenu(evt);
+ }
+ }
+ else
+ {
+ od.updateViewportFromMouse(evt.getX(), evt.getY(), av.getAlignment()
+ .getHiddenSequences(), av.getAlignment().getHiddenColumns());
+ ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
+ ap.paintAlignment(false);
+ }
}
/**
*/
public void updateOverviewImage()
{
- if (resizing)
- {
- resizeAgain = true;
- return;
- }
-
- if (av.isShowSequenceFeatures())
- {
- fr.transferSettings(ap.seqPanel.seqCanvas.fr);
- }
-
- resizing = true;
-
if ((getSize().width > 0) && (getSize().height > 0))
{
od.setWidth(getSize().width);
}
setSize(new Dimension(od.getWidth(), od.getHeight()));
+ synchronized (this)
+ {
+ if (updateRunning)
+ {
+ oviewCanvas.restartDraw();
+ return;
+ }
+
+ updateRunning = true;
+ }
Thread thread = new Thread(this);
thread.start();
repaint();
+ updateRunning = false;
}
@Override
public void run()
{
- miniMe = null;
-
- if (av.isShowSequenceFeatures())
- {
- fr.transferSettings(ap.seqPanel.seqCanvas.getFeatureRenderer());
- }
-
- if (getSize().width > 0 && getSize().height > 0)
- {
- od.setWidth(getSize().width);
- od.setHeight(getSize().height);
- }
-
- setSize(new Dimension(od.getWidth(), od.getHeight()));
-
- miniMe = nullFrame.createImage(od.getWidth(), od.getHeight());
- offscreen = nullFrame.createImage(od.getWidth(), od.getHeight());
-
- Graphics mg = miniMe.getGraphics();
-
- int alwidth = av.getAlignment().getWidth();
- int alheight = av.getAlignment().getAbsoluteHeight();
- float sampleCol = alwidth / (float) od.getWidth();
- float sampleRow = alheight / (float) od.getSequencesHeight();
-
- buildImage(sampleRow, sampleCol, mg);
-
- // check for conservation annotation to make sure overview works for DNA too
- if (av.isShowAnnotation()
- && (av.getAlignmentConservationAnnotation() != null))
- {
- for (int col = 0; col < od.getWidth() && !resizeAgain; col++)
- {
- mg.translate(col, od.getSequencesHeight());
- ap.annotationPanel.renderer.drawGraph(mg,
- av.getAlignmentConservationAnnotation(),
- av.getAlignmentConservationAnnotation().annotations,
- (int) (sampleCol) + 1, od.getGraphHeight(),
- (int) (col * sampleCol), (int) (col * sampleCol) + 1);
- mg.translate(-col, -od.getSequencesHeight());
- }
- }
- System.gc();
-
- resizing = false;
-
+ oviewCanvas.draw(av.isShowSequenceFeatures(),
+ (av.isShowAnnotation() && av
+ .getAlignmentConservationAnnotation() != null),
+ ap.seqPanel.seqCanvas.getFeatureRenderer());
setBoxPosition();
-
- if (resizeAgain)
- {
- resizeAgain = false;
- updateOverviewImage();
- }
- }
-
- /*
- * Build the overview panel image
- */
- private void buildImage(float sampleRow, float sampleCol, Graphics mg)
- {
- int lastcol = 0;
- int lastrow = 0;
- int xstart = 0;
- int ystart = 0;
- Color color = Color.yellow;
- int sameRow = 0;
- int sameCol = 0;
-
- SequenceI seq = null;
- FeatureColourFinder finder = new FeatureColourFinder(fr);
-
- final boolean hasHiddenCols = av.hasHiddenColumns();
- boolean hiddenRow = false;
-
- for (int row = 0; row <= od.getSequencesHeight() && !resizeAgain; row++)
- {
- if ((int) (row * sampleRow) == lastrow)
- {
- sameRow++;
- }
- else
- {
- // get the sequence which would be at alignment index 'lastrow' if no
- // columns were hidden, and determine whether it is hidden or not
- hiddenRow = av.getAlignment().isHidden(lastrow);
- seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow);
-
- for (int col = 0; col < od.getWidth(); col++)
- {
- if ((int) (col * sampleCol) == lastcol
- && (int) (row * sampleRow) == lastrow)
- {
- sameCol++;
- }
- else
- {
- lastcol = (int) (col * sampleCol);
-
- color = getColumnColourFromSequence(seq, hiddenRow,
- hasHiddenCols, lastcol, finder);
-
- mg.setColor(color);
- if (sameCol == 1 && sameRow == 1)
- {
- mg.drawLine(xstart, ystart, xstart, ystart);
- }
- else
- {
- mg.fillRect(xstart, ystart, sameCol, sameRow);
- }
-
- xstart = col;
- sameCol = 1;
- }
- }
- lastrow = (int) (row * sampleRow);
- ystart = row;
- sameRow = 1;
- }
- }
- }
-
- /*
- * Find the colour of a sequence at a specified column position
- */
- private Color getColumnColourFromSequence(
- jalview.datamodel.SequenceI seq, boolean hiddenRow,
- boolean hasHiddenCols, int lastcol, FeatureColourFinder finder)
- {
- Color color = Color.white;
- if (seq.getLength() > lastcol)
- {
- color = sr.getResidueColour(seq, lastcol, finder);
- }
-
- if (hiddenRow
- || (hasHiddenCols && !av.getColumnSelection()
- .isVisible(lastcol)))
- {
- color = color.darker().darker();
- }
- return color;
}
/**
public void setBoxPosition()
{
od.setBoxPosition(av.getAlignment()
- .getHiddenSequences(), av.getColumnSelection(), av.getRanges());
+.getHiddenSequences(), av
+ .getAlignment().getHiddenColumns());
repaint();
}
- @Override
- public void update(Graphics g)
+ /*
+ * Displays the popup menu and acts on user input
+ */
+ private void showPopupMenu(MouseEvent e)
{
- paint(g);
+ PopupMenu popup = new PopupMenu();
+ ItemListener menuListener = new ItemListener()
+ {
+ @Override
+ public void itemStateChanged(ItemEvent e)
+ {
+ toggleHiddenColumns();
+ }
+ };
+ CheckboxMenuItem item = new CheckboxMenuItem(
+ MessageManager.getString("label.togglehidden"));
+ item.setState(showHidden);
+ popup.add(item);
+ item.addItemListener(menuListener);
+ this.add(popup);
+ popup.show(this, e.getX(), e.getY());
}
- @Override
- public void paint(Graphics g)
+ /*
+ * Toggle overview display between showing hidden columns and hiding hidden columns
+ */
+ private void toggleHiddenColumns()
{
- Graphics og = offscreen.getGraphics();
- if (miniMe != null)
+ if (showHidden)
+ {
+ showHidden = false;
+ od = new OverviewDimensionsHideHidden(av.getRanges(),
+ (av.isShowAnnotation() && av
+ .getAlignmentConservationAnnotation() != null));
+ }
+ else
{
- og.drawImage(miniMe, 0, 0, this);
- og.setColor(Color.red);
- od.drawBox(og);
- g.drawImage(offscreen, 0, 0, this);
+ showHidden = true;
+ od = new OverviewDimensionsShowHidden(av.getRanges(),
+ (av.isShowAnnotation() && av
+ .getAlignmentConservationAnnotation() != null));
}
+ oviewCanvas.resetOviewDims(od);
+ updateOverviewImage();
}
-
}
*/
package jalview.appletgui;
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.analysis.scoremodels.SimilarityParams;
+import jalview.api.analysis.ScoreModelI;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentView;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SeqCigar;
import jalview.datamodel.SequenceI;
import jalview.util.MessageManager;
int top = 0;
- public PCAPanel(AlignViewport av)
+ public PCAPanel(AlignViewport viewport)
{
try
{
zCombobox.addItem("dim " + i);
}
- this.av = av;
- boolean selected = av.getSelectionGroup() != null
- && av.getSelectionGroup().getSize() > 0;
- AlignmentView seqstrings = av.getAlignmentView(selected);
- boolean nucleotide = av.getAlignment().isNucleotide();
+ this.av = viewport;
+ boolean selected = viewport.getSelectionGroup() != null
+ && viewport.getSelectionGroup().getSize() > 0;
+ AlignmentView seqstrings = viewport.getAlignmentView(selected);
+ boolean nucleotide = viewport.getAlignment().isNucleotide();
SequenceI[] seqs;
if (!selected)
{
- seqs = av.getAlignment().getSequencesArray();
+ seqs = viewport.getAlignment().getSequencesArray();
}
else
{
- seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
+ seqs = viewport.getSelectionGroup().getSequencesInOrder(viewport.getAlignment());
}
SeqCigar sq[] = seqstrings.getSequences();
int length = sq[0].getWidth();
return;
}
}
- pcaModel = new PCAModel(seqstrings, seqs, nucleotide);
- rc = new RotatableCanvas(av);
+ ScoreModelI scoreModel = ScoreModels.getInstance().getDefaultModel(
+ !nucleotide);
+ pcaModel = new PCAModel(seqstrings, seqs, nucleotide, scoreModel,
+ SimilarityParams.SeqSpace);
+
+ rc = new RotatableCanvas(viewport);
embedMenuIfNeeded(rc);
add(rc, BorderLayout.CENTER);
/**
* DOCUMENT ME!
*/
+ @Override
public void run()
{
// TODO progress indicator
rc.paint(rc.getGraphics());
}
+ @Override
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == inputData)
}
}
+ @Override
public void itemStateChanged(ItemEvent evt)
{
if (evt.getSource() == xCombobox)
if (!pcaModel.isNucleotide())
{
pcaModel.setNucleotide(true);
+ ScoreModelI scoreModel = ScoreModels.getInstance().getDefaultModel(
+ false);
+ pcaModel.setScoreModel(scoreModel);
new Thread(this).start();
}
}
if (pcaModel.isNucleotide())
{
pcaModel.setNucleotide(false);
+ ScoreModelI scoreModel = ScoreModels.getInstance().getDefaultModel(
+ true);
+ pcaModel.setScoreModel(scoreModel);
new Thread(this).start();
}
}
}
;
Object[] alAndColsel = pcaModel.getSeqtrings()
- .getAlignmentAndColumnSelection(gc);
+ .getAlignmentAndHiddenColumns(gc);
if (alAndColsel != null && alAndColsel[0] != null)
{
AlignFrame af = new AlignFrame(al, av.applet,
"Original Data for PCA", false);
- af.viewport.setHiddenColumns((ColumnSelection) alAndColsel[1]);
+ af.viewport.getAlignment().setHiddenColumns(
+ (HiddenColumns) alAndColsel[1]);
}
}
package jalview.appletgui;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceGroup;
import jalview.renderer.ScaleRenderer;
import jalview.renderer.ScaleRenderer.ScaleMark;
if (av.hasHiddenColumns())
{
- res = av.getColumnSelection().adjustForHiddenColumns(x);
+ res = av.getAlignment().getHiddenColumns().adjustForHiddenColumns(x);
}
else
{
});
pop.add(item);
- if (av.getColumnSelection().hasManyHiddenColumns())
+ if (av.getAlignment().getHiddenColumns().hasManyHiddenColumns())
{
item = new MenuItem(MessageManager.getString("action.reveal_all"));
item.addActionListener(new ActionListener()
if (av.hasHiddenColumns())
{
- res = av.getColumnSelection().adjustForHiddenColumns(res);
+ res = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(res);
}
if (!stretchingGroup)
int res = (evt.getX() / av.getCharWidth())
+ av.getRanges().getStartRes();
res = Math.max(0, res);
- res = cs.adjustForHiddenColumns(res);
+ res = av.getAlignment().getHiddenColumns().adjustForHiddenColumns(res);
res = Math.min(res, av.getAlignment().getWidth() - 1);
min = Math.min(res, min);
max = Math.max(res, max);
int res = (evt.getX() / av.getCharWidth())
+ av.getRanges().getStartRes();
- res = av.getColumnSelection().adjustForHiddenColumns(res);
+ res = av.getAlignment().getHiddenColumns().adjustForHiddenColumns(res);
reveal = null;
- for (int[] region : av.getColumnSelection().getHiddenColumns())
+ for (int[] region : av.getAlignment().getHiddenColumns()
+ .getHiddenRegions())
{
if (res + 1 == region[0] || res - 1 == region[1])
{
// Fill the selected columns
ColumnSelection cs = av.getColumnSelection();
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
int avCharWidth = av.getCharWidth();
int avcharHeight = av.getCharHeight();
if (cs != null)
{
gg.setColor(new Color(220, 0, 0));
- boolean hasHiddenColumns = cs.hasHiddenColumns();
+ boolean hasHiddenColumns = hidden.hasHiddenColumns();
for (int sel : cs.getSelected())
{
// TODO: JAL-2001 - provide a fast method to list visible selected in a
// given range
if (hasHiddenColumns)
{
- if (cs.isVisible(sel))
+ if (hidden.isVisible(sel))
{
- sel = cs.findColumnPosition(sel);
+ sel = hidden.findColumnPosition(sel);
}
else
{
if (av.getShowHiddenMarkers())
{
int widthx = 1 + endx - startx;
- for (int i = 0; i < cs.getHiddenColumns().size(); i++)
+ for (int i = 0; i < hidden.getHiddenRegions().size(); i++)
{
- res = cs.findHiddenRegionPosition(i) - startx;
+ res = hidden.findHiddenRegionPosition(i) - startx;
if (res < 0 || res > widthx)
{
package jalview.appletgui;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
ypos += avcharHeight;
if (av.hasHiddenColumns())
{
- startx = av.getColumnSelection().adjustForHiddenColumns(startx);
- endx = av.getColumnSelection().adjustForHiddenColumns(endx);
+ startx = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(startx);
+ endx = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(endx);
}
int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
// WEST SCALE
if (av.hasHiddenColumns())
{
- endx = av.getColumnSelection().adjustForHiddenColumns(endx);
+ endx = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(endx);
}
SequenceI seq;
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
while ((ypos <= canvasHeight) && (startRes < maxwidth))
}
if (av.hasHiddenColumns() && av.getShowHiddenMarkers())
{
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
g.setColor(Color.blue);
int res;
- for (int i = 0; i < av.getColumnSelection().getHiddenColumns()
+ for (int i = 0; i < hidden.getHiddenRegions()
.size(); i++)
{
- res = av.getColumnSelection().findHiddenRegionPosition(i)
+ res = hidden.findHiddenRegionPosition(i)
- startRes;
if (res < 0 || res > endx - startRes)
g.setClip(0, 0, cWidth * avcharWidth, canvasHeight);
}
- drawPanel(g, startRes, endx, 0, al.getHeight(), ypos);
+ drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
g.setClip(null);
if (av.isShowAnnotation())
if (av.hasHiddenColumns())
{
- for (int[] region : av.getColumnSelection().getHiddenColumns())
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ for (int[] region : hidden.getHiddenRegions())
{
int hideStart = region[0];
int hideEnd = region[1];
g1.setColor(Color.blue);
g1.drawLine((blockEnd - blockStart + 1) * avcharWidth - 1,
0 + offset, (blockEnd - blockStart + 1) * avcharWidth
- - 1, (endSeq - startSeq) * avcharHeight
+ - 1, (endSeq - startSeq + 1) * avcharHeight
+ offset);
}
import jalview.commands.EditCommand.Action;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
seqCanvas.cursorX += dx;
seqCanvas.cursorY += dy;
if (av.hasHiddenColumns()
- && !av.getColumnSelection().isVisible(seqCanvas.cursorX))
+ && !av.getAlignment().getHiddenColumns()
+ .isVisible(seqCanvas.cursorX))
{
int original = seqCanvas.cursorX - dx;
int maxWidth = av.getAlignment().getWidth();
- while (!av.getColumnSelection().isVisible(seqCanvas.cursorX)
+ while (!av.getAlignment().getHiddenColumns()
+ .isVisible(seqCanvas.cursorX)
&& seqCanvas.cursorX < maxWidth && seqCanvas.cursorX > 0)
{
seqCanvas.cursorX += dx;
}
if (seqCanvas.cursorX >= maxWidth
- || !av.getColumnSelection().isVisible(seqCanvas.cursorX))
+ || !av.getAlignment().getHiddenColumns()
+ .isVisible(seqCanvas.cursorX))
{
seqCanvas.cursorX = original;
}
else
{
ViewportRanges ranges = av.getRanges();
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
while (seqCanvas.cursorY < ranges.getStartSeq())
{
ap.scrollUp(true);
}
- while (seqCanvas.cursorY + 1 > ranges.getEndSeq())
+ while (seqCanvas.cursorY > ranges.getEndSeq())
{
ap.scrollUp(false);
}
- while (seqCanvas.cursorX < av.getColumnSelection()
- .adjustForHiddenColumns(ranges.getStartRes()))
+ while (seqCanvas.cursorX < hidden.adjustForHiddenColumns(ranges
+ .getStartRes()))
{
if (!ap.scrollRight(false))
break;
}
}
- while (seqCanvas.cursorX > av.getColumnSelection()
- .adjustForHiddenColumns(ranges.getEndRes()))
+ while (seqCanvas.cursorX > hidden.adjustForHiddenColumns(ranges
+ .getEndRes()))
{
if (!ap.scrollRight(true))
{
if (av.hasHiddenColumns())
{
- res = av.getColumnSelection().adjustForHiddenColumns(res);
+ res = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(res);
}
return res;
fontSize = 1;
}
- av.setFont(new Font(av.font.getName(), av.font.getStyle(), fontSize));
+ av.setFont(
+ new Font(av.font.getName(), av.font.getStyle(), fontSize),
+ true);
av.setCharWidth(oldWidth);
}
else
if (av.hasHiddenColumns())
{
fixedColumns = true;
- int y1 = av.getColumnSelection().getHiddenBoundaryLeft(startres);
- int y2 = av.getColumnSelection().getHiddenBoundaryRight(startres);
+ int y1 = av.getAlignment().getHiddenColumns()
+ .getHiddenBoundaryLeft(startres);
+ int y2 = av.getAlignment().getHiddenColumns()
+ .getHiddenBoundaryRight(startres);
if ((insertGap && startres > y1 && lastres < y1)
|| (!insertGap && startres < y2 && lastres > y2))
{
if (sg.getSize() == av.getAlignment().getHeight())
{
- if ((av.hasHiddenColumns() && startres < av
- .getColumnSelection().getHiddenBoundaryRight(startres)))
+ if ((av.hasHiddenColumns() && startres < av.getAlignment()
+ .getHiddenColumns().getHiddenBoundaryRight(startres)))
{
endEditing();
return;
*/
@Override
public void selection(SequenceGroup seqsel, ColumnSelection colsel,
- SelectionSource source)
+ HiddenColumns hidden, SelectionSource source)
{
// TODO: fix this hack - source of messages is align viewport, but SeqPanel
// handles selection messages...
* Check for selection in a view of which this one is a dna/protein
* complement.
*/
- if (selectionFromTranslation(seqsel, colsel, source))
+ if (selectionFromTranslation(seqsel, colsel, hidden, source))
{
return;
}
}
else
{
- av.getColumnSelection().setElementsFrom(colsel);
+ av.getColumnSelection().setElementsFrom(colsel,
+ av.getAlignment().getHiddenColumns());
}
}
repaint |= av.isColSelChanged(true);
}
if (copycolsel
&& av.hasHiddenColumns()
- && (av.getColumnSelection() == null || av.getColumnSelection()
- .getHiddenColumns() == null))
+ && (av.getColumnSelection() == null || av.getAlignment()
+ .getHiddenColumns().getHiddenRegions() == null))
{
System.err.println("Bad things");
}
* @param source
*/
protected boolean selectionFromTranslation(SequenceGroup seqsel,
- ColumnSelection colsel, SelectionSource source)
+ ColumnSelection colsel, HiddenColumns hidden,
+ SelectionSource source)
{
if (!(source instanceof AlignViewportI))
{
/*
* Map column selection
*/
- ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, sourceAv,
- av);
+ // ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, sourceAv,
+ // av);
+ ColumnSelection cs = new ColumnSelection();
+ HiddenColumns hs = new HiddenColumns();
+ MappingUtils.mapColumnSelection(colsel, hidden, sourceAv, av, cs, hs);
av.setColumnSelection(cs);
+ av.getAlignment().setHiddenColumns(hs);
ap.scalePanelHolder.repaint();
ap.repaint();
void getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
{
- if (shader != null)
+ if (shader.getColourScheme() != null)
{
resBoxColour = shader.findColour(seq.getCharAt(i), i, seq);
}
package jalview.appletgui;
import jalview.analysis.Conservation;
-import jalview.analysis.NJTree;
+import jalview.analysis.TreeModel;
import jalview.api.AlignViewportI;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceGroup;
import java.awt.event.MouseMotionListener;
import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.List;
import java.util.Vector;
public class TreeCanvas extends Panel implements MouseListener,
MouseMotionListener
{
- NJTree tree;
+ TreeModel tree;
ScrollPane scrollPane;
selected.addOrRemove(sequence, true);
}
- public void setTree(NJTree tree)
+ public void setTree(TreeModel tree2)
{
- this.tree = tree;
- tree.findHeight(tree.getTopNode());
+ this.tree = tree2;
+ tree2.findHeight(tree2.getTopNode());
// Now have to calculate longest name based on the leaves
- Vector<SequenceNode> leaves = tree.findLeaves(tree.getTopNode());
+ Vector<SequenceNode> leaves = tree2.findLeaves(tree2.getTopNode());
boolean has_placeholders = false;
longestName = "";
}
public void drawNode(Graphics g, SequenceNode node, float chunk,
- float scale, int width, int offx, int offy)
+ double scale, int width, int offx, int offy)
{
if (node == null)
{
{
// Drawing leaf node
- float height = node.height;
- float dist = node.dist;
+ double height = node.height;
+ double dist = node.dist;
int xstart = (int) ((height - dist) * scale) + offx;
int xend = (int) (height * scale) + offx;
drawNode(g, (SequenceNode) node.right(), chunk, scale, width, offx,
offy);
- float height = node.height;
- float dist = node.dist;
+ double height = node.height;
+ double dist = node.dist;
int xstart = (int) ((height - dist) * scale) + offx;
int xend = (int) (height * scale) + offx;
SequenceNode top = tree.getTopNode();
- float wscale = (float) (width * .8 - offx * 2) / tree.getMaxHeight();
+ double wscale = (float) (width * .8 - offx * 2) / tree.getMaxHeight();
if (top.count == 0)
{
top.count = ((SequenceNode) top.left()).count
}
public void pickNode(Rectangle pickBox, SequenceNode node, float chunk,
- float scale, int width, int offx, int offy)
+ double scale, int width, int offx, int offy)
{
if (node == null)
{
if (node.left() == null && node.right() == null)
{
- float height = node.height;
+ double height = node.height;
// float dist = node.dist;
// int xstart = (int) ( (height - dist) * scale) + offx;
// for
// scrollbar
- float wscale = (width - labelLength - offx * 2) / tree.getMaxHeight();
+ double wscale = (width - labelLength - offx * 2) / tree.getMaxHeight();
SequenceNode top = tree.getTopNode();
threshold = (float) (x - offx)
/ (float) (getSize().width - labelLength - 2 * offx);
- tree.getGroups().removeAllElements();
- tree.groupNodes(tree.getTopNode(), threshold);
+ List<SequenceNode> groups = tree.groupNodes(threshold);
setColor(tree.getTopNode(), Color.black);
av.setSelectionGroup(null);
codingComplement.clearSequenceColours();
}
- colourGroups();
+ colourGroups(groups);
}
}
}
- void colourGroups()
+ void colourGroups(List<SequenceNode> groups)
{
- for (int i = 0; i < tree.getGroups().size(); i++)
+ for (int i = 0; i < groups.size(); i++)
{
Color col = new Color((int) (Math.random() * 255),
(int) (Math.random() * 255), (int) (Math.random() * 255));
- setColor(tree.getGroups().elementAt(i), col.brighter());
+ setColor(groups.get(i), col.brighter());
- Vector<SequenceNode> l = tree.findLeaves(tree.getGroups()
- .elementAt(i));
+ Vector<SequenceNode> l = tree.findLeaves(groups.get(i));
Vector<SequenceI> sequences = new Vector<SequenceI>();
for (int j = 0; j < l.size(); j++)
*/
package jalview.appletgui;
+import jalview.analysis.AverageDistanceTree;
import jalview.analysis.NJTree;
+import jalview.analysis.TreeBuilder;
+import jalview.analysis.TreeModel;
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.analysis.scoremodels.SimilarityParams;
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.HiddenColumns;
import jalview.datamodel.SequenceI;
import jalview.io.NewickFile;
-import jalview.schemes.ResidueProperties;
import jalview.util.MessageManager;
import java.awt.BorderLayout;
TreeCanvas treeCanvas;
- NJTree tree;
+ TreeModel tree;
AlignmentPanel ap;
AlignViewport av;
- public NJTree getTree()
+ public TreeModel getTree()
{
return tree;
}
+ @Override
public void finalize() throws Throwable
{
ap = null;
/**
* Creates a new TreePanel object.
- *
- * @param av
- * DOCUMENT ME!
- * @param seqVector
- * DOCUMENT ME!
- * @param type
- * DOCUMENT ME!
- * @param pwtype
- * DOCUMENT ME!
- * @param s
- * DOCUMENT ME!
- * @param e
- * DOCUMENT ME!
*/
- public TreePanel(AlignmentPanel ap, String type, String pwtype)
+ public TreePanel(AlignmentPanel alignPanel, String type, String pwtype)
{
try
{
ex.printStackTrace();
}
- initTreePanel(ap, type, pwtype, null);
+ initTreePanel(alignPanel, type, pwtype, null);
}
/**
* Creates a new TreePanel object.
*
- * @param av
- * DOCUMENT ME!
- * @param seqVector
- * DOCUMENT ME!
- * @param newtree
- * DOCUMENT ME!
- * @param type
- * DOCUMENT ME!
- * @param pwtype
- * DOCUMENT ME!
*/
public TreePanel(AlignmentPanel ap, String type, String pwtype,
NewickFile newtree)
// yields unaligned seqs)
// or create a selection box around columns in alignment view
// test Alignment(SeqCigar[])
- if (tree.seqData != null)
+ if (tree.getOriginalData() != null)
{
char gc = '-';
try
} catch (Exception ex)
{
}
- ;
- Object[] alAndColsel = tree.seqData
- .getAlignmentAndColumnSelection(gc);
+
+ Object[] alAndColsel = tree.getOriginalData()
+ .getAlignmentAndHiddenColumns(gc);
if (alAndColsel != null && alAndColsel[0] != null)
{
AlignFrame af = new AlignFrame(al, av.applet,
"Original Data for Tree", false);
- af.viewport.setHiddenColumns((ColumnSelection) alAndColsel[1]);
+ af.viewport.getAlignment().setHiddenColumns(
+ (HiddenColumns) alAndColsel[1]);
}
}
else
this.newtree = newtree;
}
+ @Override
public void run()
{
if (newtree != null)
{
- if (odata == null)
- {
- tree = new NJTree(av.getAlignment().getSequencesArray(), newtree);
- }
- else
- {
- tree = new NJTree(av.getAlignment().getSequencesArray(), odata,
- newtree);
- }
-
+ tree = new TreeModel(av.getAlignment().getSequencesArray(), odata,
+ newtree);
}
else
{
- int start, end;
- SequenceI[] seqs;
- boolean selview = av.getSelectionGroup() != null
- && av.getSelectionGroup().getSize() > 1;
- AlignmentView seqStrings = av.getAlignmentView(selview);
- if (!selview)
- {
- start = 0;
- end = av.getAlignment().getWidth();
- seqs = av.getAlignment().getSequencesArray();
- }
- else
- {
- start = av.getSelectionGroup().getStartRes();
- end = av.getSelectionGroup().getEndRes() + 1;
- seqs = av.getSelectionGroup().getSequencesInOrder(
- av.getAlignment());
- }
- 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);
- }
+ ScoreModelI sm1 = ScoreModels.getInstance().getScoreModel(pwtype,
+ treeCanvas.ap);
+ ScoreModelI sm = sm1;
+ TreeBuilder njtree = type.equals(TreeBuilder.NEIGHBOUR_JOINING) ? new NJTree(
+ av, sm, SimilarityParams.Jalview)
+ : new AverageDistanceTree(av, sm, SimilarityParams.Jalview);
+ tree = new TreeModel(njtree);
}
tree.reCount(tree.getTopNode());
}
}
+ @Override
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == newickOutput)
}
}
+ @Override
public void itemStateChanged(ItemEvent evt)
{
if (evt.getSource() == fitToWindow)
data = aparser.getValue("tree", true);
if (data != null)
{
- jalview.io.NewickFile fin = null;
try
{
System.out.println("CMD [-tree " + data
+ "] executed successfully!");
- fin = new NewickFile(data,
+ NewickFile nf = new NewickFile(data,
AppletFormatAdapter.checkProtocol(data));
- if (fin != null)
- {
- af.getViewport().setCurrentTree(
- af.ShowNewickTree(fin, data).getTree());
- }
+ af.getViewport().setCurrentTree(
+ af.showNewickTree(nf, data).getTree());
} catch (IOException ex)
{
System.err.println("Couldn't add tree " + data);
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceGroup;
@Override
public void run()
{
- alf.select(sel, csel);
+ alf.select(sel, csel, alf.getAlignViewport().getAlignment()
+ .getHiddenColumns());
}
});
}
SequenceI repseq = alignFrame.viewport.getAlignment()
.getSequenceAt(0);
alignFrame.viewport.getAlignment().setSeqrep(repseq);
- ColumnSelection cs = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
cs.hideInsertionsFor(repseq);
- alignFrame.viewport.setColumnSelection(cs);
+ alignFrame.viewport.getAlignment().setHiddenColumns(cs);
alignFrame.alignPanel.fontChanged();
alignFrame.alignPanel.setScrollValues(0, 0);
result = true;
HiddenSequences hiddenSequences;
+ HiddenColumns hiddenCols;
+
public Hashtable alignmentProperties;
private List<AlignedCodonFrame> codonFrameList;
{
groups = Collections.synchronizedList(new ArrayList<SequenceGroup>());
hiddenSequences = new HiddenSequences(this);
+ hiddenCols = new HiddenColumns();
codonFrameList = new ArrayList<AlignedCodonFrame>();
nucleotide = Comparison.isNucleotide(seqs);
public Alignment(SeqCigar[] alseqs)
{
SequenceI[] seqs = SeqCigar.createAlignmentSequences(alseqs,
- gapCharacter, new ColumnSelection(), null);
+ gapCharacter, new HiddenColumns(), null);
initAlignment(seqs);
}
}
@Override
+ public HiddenColumns getHiddenColumns()
+ {
+ return hiddenCols;
+ }
+
+ @Override
public CigarArray getCompactAlignment()
{
synchronized (sequences)
return aa;
}
- /**
- * Returns an iterable collection of any annotations that match on given
- * sequence ref, calcId and label (ignoring null values).
- */
@Override
public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
String calcId, String label)
ArrayList<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
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))
+ if ((calcId == null || (ann.getCalcId() != null && ann.getCalcId()
+ .equals(calcId)))
+ && (seq == null || (ann.sequenceRef != null && ann.sequenceRef == seq))
+ && (label == null || (ann.label != null && ann.label
+ .equals(label))))
{
aa.add(ann);
}
}
return new int[] { startPos, endPos };
}
+
+ @Override
+ public void setHiddenColumns(HiddenColumns cols)
+ {
+ hiddenCols = cols;
+ }
}
*/
package jalview.datamodel;
+import jalview.analysis.Rna;
+import jalview.analysis.SecStrConsensus.SimpleBP;
+import jalview.analysis.WUSSParseException;
+
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
-import jalview.analysis.Rna;
-import jalview.analysis.SecStrConsensus.SimpleBP;
-import jalview.analysis.WUSSParseException;
-
/**
* DOCUMENT ME!
*
* @param colSel
*/
public AlignmentAnnotation(AlignmentAnnotation alignmentAnnotation,
- ColumnSelection colSel)
+ HiddenColumns hidden)
{
this(alignmentAnnotation);
if (annotations == null)
{
return;
}
- colSel.makeVisibleAnnotation(this);
+ hidden.makeVisibleAnnotation(this);
}
public void setPadGaps(boolean padgaps, char gapchar)
{
return counter++;
}
+
+ /**
+ *
+ * @return true for rows that have a range of values in their annotation set
+ */
+ public boolean isQuantitative()
+ {
+ return graphMin < graphMax;
+ }
}
HiddenSequences getHiddenSequences();
+ HiddenColumns getHiddenColumns();
+
/**
* Compact representation of alignment
*
*/
public int[] getVisibleStartAndEndIndex(List<int[]> hiddenCols);
+ public void setHiddenColumns(HiddenColumns cols);
+
}
* the view
*/
public AlignmentView(AlignmentI alignment,
- ColumnSelection columnSelection, SequenceGroup selection,
+ HiddenColumns hidden,
+ SequenceGroup selection,
boolean hasHiddenColumns, boolean selectedRegionOnly,
boolean recordGroups)
{
// refactored from AlignViewport.getAlignmentView(selectedOnly);
this(new jalview.datamodel.CigarArray(alignment,
- (hasHiddenColumns ? columnSelection : null),
+ (hasHiddenColumns ? hidden : null),
(selectedRegionOnly ? selection : null)),
(selectedRegionOnly && selection != null) ? selection
.getStartRes() : 0);
* char
* @return Object[] { SequenceI[], ColumnSelection}
*/
- public Object[] getAlignmentAndColumnSelection(char gapCharacter)
+ public Object[] getAlignmentAndHiddenColumns(char gapCharacter)
{
- ColumnSelection colsel = new ColumnSelection();
+ HiddenColumns hidden = new HiddenColumns();
return new Object[] {
- SeqCigar.createAlignmentSequences(sequences, gapCharacter, colsel,
- contigs), colsel };
+ SeqCigar.createAlignmentSequences(sequences, gapCharacter, hidden,
+ contigs), hidden };
}
/**
if (contigs != null && contigs.length > 0)
{
SequenceI[] alignment = new SequenceI[sequences.length];
- ColumnSelection columnselection = new ColumnSelection();
+ // ColumnSelection columnselection = new ColumnSelection();
+ HiddenColumns hidden = new HiddenColumns();
if (contigs != null && contigs.length > 0)
{
int start = 0;
}
}
// mark hidden segment as hidden in the new alignment
- columnselection.hideColumns(nwidth, nwidth + contigs[contig + 2]
+ hidden.hideColumns(nwidth, nwidth + contigs[contig + 2]
- 1);
nwidth += contigs[contig + 2];
}
}
}
}
- return new Object[] { alignment, columnselection };
+ return new Object[] { alignment, hidden };
}
else
{
}
if (nvismsa[0] != null)
{
- return new Object[] { nvismsa[0], new ColumnSelection() };
+ return new Object[] { nvismsa[0], new HiddenColumns() };
}
else
{
- return getAlignmentAndColumnSelection(gapCharacter);
+ return getAlignmentAndHiddenColumns(gapCharacter);
}
}
}
if (start < fwidth)
{
viscontigs[nvis] = start;
- viscontigs[nvis + 1] = fwidth; // end is inclusive
+ viscontigs[nvis + 1] = fwidth - 1; // end is inclusive
nvis += 2;
}
return viscontigs;
}
else
{
- return new int[] { 0, width };
+ return new int[] { 0, width - 1 };
}
}
}
public static void testSelectionViews(AlignmentI alignment,
- ColumnSelection csel, SequenceGroup selection)
+ HiddenColumns hidden, SequenceGroup selection)
{
System.out.println("Testing standard view creation:\n");
AlignmentView view = null;
{
System.out
.println("View with no hidden columns, no limit to selection, no groups to be collected:");
- view = new AlignmentView(alignment, csel, selection, false, false,
+ view = new AlignmentView(alignment, hidden, selection, false, false,
false);
summariseAlignmentView(view, System.out);
{
System.out
.println("View with no hidden columns, no limit to selection, and all groups to be collected:");
- view = new AlignmentView(alignment, csel, selection, false, false,
+ view = new AlignmentView(alignment, hidden, selection, false, false,
true);
summariseAlignmentView(view, System.out);
} catch (Exception e)
{
System.out
.println("View with no hidden columns, limited to selection and no groups to be collected:");
- view = new AlignmentView(alignment, csel, selection, false, true,
+ view = new AlignmentView(alignment, hidden, selection, false, true,
false);
summariseAlignmentView(view, System.out);
} catch (Exception e)
{
System.out
.println("View with no hidden columns, limited to selection, and all groups to be collected:");
- view = new AlignmentView(alignment, csel, selection, false, true,
+ view = new AlignmentView(alignment, hidden, selection, false, true,
true);
summariseAlignmentView(view, System.out);
} catch (Exception e)
{
System.out
.println("View *with* hidden columns, no limit to selection, no groups to be collected:");
- view = new AlignmentView(alignment, csel, selection, true, false,
+ view = new AlignmentView(alignment, hidden, selection, true, false,
false);
summariseAlignmentView(view, System.out);
} catch (Exception e)
{
System.out
.println("View *with* hidden columns, no limit to selection, and all groups to be collected:");
- view = new AlignmentView(alignment, csel, selection, true, false,
+ view = new AlignmentView(alignment, hidden, selection, true, false,
true);
summariseAlignmentView(view, System.out);
} catch (Exception e)
{
System.out
.println("View *with* hidden columns, limited to selection and no groups to be collected:");
- view = new AlignmentView(alignment, csel, selection, true, true,
+ view = new AlignmentView(alignment, hidden, selection, true, true,
false);
summariseAlignmentView(view, System.out);
} catch (Exception e)
{
System.out
.println("View *with* hidden columns, limited to selection, and all groups to be collected:");
- view = new AlignmentView(alignment, csel, selection, true, true, true);
+ view = new AlignmentView(alignment, hidden, selection, true, true,
+ true);
summariseAlignmentView(view, System.out);
} catch (Exception e)
{
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import jalview.api.AlignmentColsCollectionI;
+
+import java.util.Iterator;
+
+public class AllColsCollection implements AlignmentColsCollectionI
+{
+ int start;
+ int end;
+
+ HiddenColumns hidden;
+
+ public AllColsCollection(int s, int e, AlignmentI al)
+ {
+ start = s;
+ end = e;
+ hidden = al.getHiddenColumns();
+ }
+
+ @Override
+ public Iterator<Integer> iterator()
+ {
+ return new AllColsIterator(start,end,hidden);
+ }
+
+ @Override
+ public boolean isHidden(int c)
+ {
+ return !hidden.isVisible(c);
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator which iterates over all columns or rows in an alignment, whether
+ * hidden or visible.
+ *
+ * @author kmourao
+ *
+ */
+public class AllColsIterator implements Iterator<Integer>
+{
+ private int last;
+
+ private int next;
+
+ private int current;
+
+ public AllColsIterator(int firstcol, int lastcol, HiddenColumns hiddenCols)
+ {
+ last = lastcol;
+ next = firstcol;
+ current = firstcol;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return next <= last;
+ }
+
+ @Override
+ public Integer next()
+ {
+ if (next > last)
+ {
+ throw new NoSuchElementException();
+ }
+ current = next;
+ next++;
+
+ return current;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
+
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import jalview.api.AlignmentRowsCollectionI;
+
+import java.util.Iterator;
+
+public class AllRowsCollection implements AlignmentRowsCollectionI
+{
+ int start;
+
+ int end;
+
+ AlignmentI alignment;
+
+ HiddenSequences hidden;
+
+ public AllRowsCollection(int s, int e, AlignmentI al)
+ {
+ start = s;
+ end = e;
+ alignment = al;
+ hidden = al.getHiddenSequences();
+ }
+
+ @Override
+ public Iterator<Integer> iterator()
+ {
+ return new AllRowsIterator(start, end, alignment);
+ }
+
+ @Override
+ public boolean isHidden(int seq)
+ {
+ return hidden.isHidden(seq);
+ }
+
+ @Override
+ public SequenceI getSequence(int seq)
+ {
+ return alignment.getSequenceAtAbsoluteIndex(seq);
+ }
+}
+
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator which iterates over all columns or rows in an alignment, whether
+ * hidden or visible.
+ *
+ * @author kmourao
+ *
+ */
+public class AllRowsIterator implements Iterator<Integer>
+{
+ private int last;
+
+ private int next;
+
+ private int current;
+
+ private AlignmentI al;
+
+ public AllRowsIterator(int firstrow, int lastrow, AlignmentI alignment)
+ {
+ last = lastrow;
+ current = firstrow;
+ next = firstrow;
+ al = alignment;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return next <= last;
+ }
+
+ @Override
+ public Integer next()
+ {
+ if (next > last)
+ {
+ throw new NoSuchElementException();
+ }
+ current = next;
+ next++;
+
+ return current;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
+
+
*/
Iterable<AlignmentAnnotation> findAnnotation(String calcId);
+ /**
+ * Returns an iterable collection of any annotations that match on given
+ * sequence ref, calcId and label (ignoring null values).
+ *
+ * @param seq
+ * null or reference sequence to select annotation for
+ * @param calcId
+ * null or the calcId to select annotation for
+ * @param label
+ * null or the label to select annotation for
+ */
Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
String calcId, String label);
*/
public class Annotation
{
+ /**
+ * the empty annotation - proxy for null entries in annotation row
+ */
+ public static final Annotation EMPTY_ANNOTATION = new Annotation("", "",
+ ' ', 0f);
+
/** Character label - also shown below histogram */
public String displayCharacter = "";
}
return sb.toString();
}
+
+ /**
+ * @return true if annot is 'whitespace' annotation (zero score, whitespace or
+ * zero length display character, label, description
+ */
+ public boolean isWhitespace()
+ {
+ return ((value == 0f)
+ && ((description == null) || (description.trim()
+ .length() == 0))
+ && ((displayCharacter == null) || (displayCharacter
+ .trim().length() == 0))
+ && (secondaryStructure == '\0' || (secondaryStructure == ' ')) && colour == null);
+ }
}
*/
package jalview.datamodel;
+import jalview.analysis.scoremodels.ScoreMatrix;
import jalview.schemes.ResidueProperties;
-import jalview.schemes.ScoreMatrix;
/**
* Encode a sequence as a numeric vector using either classic residue binary
/**
* ancode using substitution matrix given in matrix
*
- * @param matrix
+ * @param smtrx
*/
- public void matrixEncode(final ScoreMatrix matrix)
+ public void matrixEncode(final ScoreMatrix smtrx)
throws InvalidSequenceTypeException
{
- if (isNa != matrix.isDNA())
+ if (isNa != smtrx.isDNA())
{
throw new InvalidSequenceTypeException("matrix "
- + matrix.getClass().getCanonicalName()
+ + smtrx.getClass().getCanonicalName()
+ " is not a valid matrix for "
+ (isNa ? "nucleotide" : "protein") + "sequences");
}
- matrixEncode(matrix.isDNA() ? ResidueProperties.nucleotideIndex
- : ResidueProperties.aaIndex, matrix.getMatrix());
+ matrixEncode(smtrx.isDNA() ? ResidueProperties.nucleotideIndex
+ : ResidueProperties.aaIndex, smtrx.getMatrix());
}
- private void matrixEncode(final int[] aaIndex, final int[][] matrix)
+ private void matrixEncode(final int[] aaIndex, final float[][] matrix)
{
int nores = initMatrixGetNoRes();
* @param columnSelection
* @param selectionGroup
*/
- public CigarArray(AlignmentI alignment, ColumnSelection columnSelection,
+ public CigarArray(AlignmentI alignment, HiddenColumns hidden,
SequenceGroup selectionGroup)
{
this(constructSeqCigarArray(alignment, selectionGroup));
constructFromAlignment(alignment,
- columnSelection != null ? columnSelection.getHiddenColumns()
+ hidden != null ? hidden.getHiddenRegions()
: null, selectionGroup);
}
}
/**
- * @see Cigar.getSequenceAndDeletions
+ * @see CigarBase.getSequenceAndDeletions
* @param GapChar
* char
* @return Object[][]
*/
package jalview.datamodel;
-import jalview.util.Comparison;
-import jalview.util.ShiftList;
import jalview.viewmodel.annotationfilter.AnnotationFilterParameter;
import jalview.viewmodel.annotationfilter.AnnotationFilterParameter.SearchableAnnotationField;
import java.util.BitSet;
import java.util.Collections;
import java.util.List;
-import java.util.Vector;
/**
* Data class holding the selected columns and hidden column ranges for a view.
IntList selection = new IntList();
- /*
- * list of hidden column [start, end] ranges; the list is maintained in
- * ascending start column order
- */
- Vector<int[]> hiddenColumns;
-
/**
* Add a column to the selection
*
}
/**
- *
- * @param col
- * index to search for in column selection
- *
- * @return true if col is selected
- */
- public boolean contains(int col)
- {
- return (col > -1) ? selection.isSelected(col) : false;
- }
-
- /**
- * Answers true if no columns are selected, else false
- */
- public boolean isEmpty()
- {
- return selection == null || selection.isEmpty();
- }
-
- /**
- * rightmost selected column
- *
- * @return rightmost column in alignment that is selected
- */
- public int getMax()
- {
- if (selection.isEmpty())
- {
- return -1;
- }
- return selection.getMaxColumn();
- }
-
- /**
- * Leftmost column in selection
- *
- * @return column index of leftmost column in selection
- */
- public int getMin()
- {
- if (selection.isEmpty())
- {
- return 1000000000;
- }
- return selection.getMinColumn();
- }
-
- /**
- * propagate shift in alignment columns to column selection
- *
- * @param start
- * beginning of edit
- * @param left
- * shift in edit (+ve for removal, or -ve for inserts)
- */
- public List<int[]> compensateForEdit(int start, int change)
- {
- List<int[]> deletedHiddenColumns = null;
- selection.compensateForEdits(start, change);
-
- if (hiddenColumns != null)
- {
- deletedHiddenColumns = new ArrayList<int[]>();
- int hSize = hiddenColumns.size();
- for (int i = 0; i < hSize; i++)
- {
- int[] region = hiddenColumns.elementAt(i);
- if (region[0] > start && start + change > region[1])
- {
- deletedHiddenColumns.add(region);
-
- hiddenColumns.removeElementAt(i);
- i--;
- hSize--;
- continue;
- }
-
- if (region[0] > start)
- {
- region[0] -= change;
- region[1] -= change;
- }
-
- if (region[0] < 0)
- {
- region[0] = 0;
- }
-
- }
-
- this.revealHiddenColumns(0);
- }
-
- return deletedHiddenColumns;
- }
-
- /**
- * propagate shift in alignment columns to column selection special version of
- * compensateForEdit - allowing for edits within hidden regions
- *
- * @param start
- * beginning of edit
- * @param left
- * shift in edit (+ve for removal, or -ve for inserts)
- */
- private void compensateForDelEdits(int start, int change)
- {
-
- selection.compensateForEdits(start, change);
-
- if (hiddenColumns != null)
- {
- for (int i = 0; i < hiddenColumns.size(); i++)
- {
- int[] region = hiddenColumns.elementAt(i);
- if (region[0] >= start)
- {
- region[0] -= change;
- }
- if (region[1] >= start)
- {
- region[1] -= change;
- }
- if (region[1] < region[0])
- {
- hiddenColumns.removeElementAt(i--);
- }
-
- if (region[0] < 0)
- {
- region[0] = 0;
- }
- if (region[1] < 0)
- {
- region[1] = 0;
- }
- }
- }
- }
-
- /**
- * Adjust hidden column boundaries based on a series of column additions or
- * deletions in visible regions.
- *
- * @param shiftrecord
- * @return
- */
- public ShiftList compensateForEdits(ShiftList shiftrecord)
- {
- if (shiftrecord != null)
- {
- final List<int[]> shifts = shiftrecord.getShifts();
- if (shifts != null && shifts.size() > 0)
- {
- int shifted = 0;
- for (int i = 0, j = shifts.size(); i < j; i++)
- {
- int[] sh = shifts.get(i);
- // compensateForEdit(shifted+sh[0], sh[1]);
- compensateForDelEdits(shifted + sh[0], sh[1]);
- shifted -= sh[1];
- }
- }
- return shiftrecord.getInverse();
- }
- return null;
- }
-
- /**
- * removes intersection of position,length ranges in deletions from the
- * start,end regions marked in intervals.
- *
- * @param shifts
- * @param intervals
- * @return
- */
- private boolean pruneIntervalVector(final List<int[]> shifts,
- Vector<int[]> intervals)
- {
- boolean pruned = false;
- int i = 0, j = intervals.size() - 1, s = 0, t = shifts.size() - 1;
- int hr[] = intervals.elementAt(i);
- int sr[] = shifts.get(s);
- while (i <= j && s <= t)
- {
- boolean trailinghn = hr[1] >= sr[0];
- if (!trailinghn)
- {
- if (i < j)
- {
- hr = intervals.elementAt(++i);
- }
- else
- {
- i++;
- }
- continue;
- }
- int endshift = sr[0] + sr[1]; // deletion ranges - -ve means an insert
- if (endshift < hr[0] || endshift < sr[0])
- { // leadinghc disjoint or not a deletion
- if (s < t)
- {
- sr = shifts.get(++s);
- }
- else
- {
- s++;
- }
- continue;
- }
- boolean leadinghn = hr[0] >= sr[0];
- boolean leadinghc = hr[0] < endshift;
- boolean trailinghc = hr[1] < endshift;
- if (leadinghn)
- {
- if (trailinghc)
- { // deleted hidden region.
- intervals.removeElementAt(i);
- pruned = true;
- j--;
- if (i <= j)
- {
- hr = intervals.elementAt(i);
- }
- continue;
- }
- if (leadinghc)
- {
- hr[0] = endshift; // clip c terminal region
- leadinghn = !leadinghn;
- pruned = true;
- }
- }
- if (!leadinghn)
- {
- if (trailinghc)
- {
- if (trailinghn)
- {
- hr[1] = sr[0] - 1;
- pruned = true;
- }
- }
- else
- {
- // sr contained in hr
- if (s < t)
- {
- sr = shifts.get(++s);
- }
- else
- {
- s++;
- }
- continue;
- }
- }
- }
- return pruned; // true if any interval was removed or modified by
- // operations.
- }
-
- /**
- * remove any hiddenColumns or selected columns and shift remaining based on a
- * series of position, range deletions.
- *
- * @param deletions
- */
- public void pruneDeletions(ShiftList deletions)
- {
- if (deletions != null)
- {
- final List<int[]> shifts = deletions.getShifts();
- if (shifts != null && shifts.size() > 0)
- {
- // delete any intervals intersecting.
- if (hiddenColumns != null)
- {
- pruneIntervalVector(shifts, hiddenColumns);
- if (hiddenColumns != null && hiddenColumns.size() == 0)
- {
- hiddenColumns = null;
- }
- }
- if (selection != null && selection.size() > 0)
- {
- selection.pruneColumnList(shifts);
- if (selection != null && selection.size() == 0)
- {
- selection = null;
- }
- }
- // and shift the rest.
- this.compensateForEdits(deletions);
- }
- }
- }
-
- /**
- * This Method is used to return all the HiddenColumn regions
- *
- * @return empty list or List of hidden column intervals
- */
- public List<int[]> getHiddenColumns()
- {
- return hiddenColumns == null ? Collections.<int[]> emptyList()
- : hiddenColumns;
- }
-
- /**
- * Return absolute column index for a visible column index
- *
- * @param column
- * int column index in alignment view (count from zero)
- * @return alignment column index for column
- */
- public int adjustForHiddenColumns(int column)
- {
- int result = column;
- if (hiddenColumns != null)
- {
- for (int i = 0; i < hiddenColumns.size(); i++)
- {
- int[] region = hiddenColumns.elementAt(i);
- if (result >= region[0])
- {
- result += region[1] - region[0] + 1;
- }
- }
- }
- return result;
- }
-
- /**
- * Use this method to find out where a column will appear in the visible
- * alignment when hidden columns exist. If the column is not visible, then the
- * left-most visible column will always be returned.
- *
- * @param hiddenColumn
- * the column index in the full alignment including hidden columns
- * @return the position of the column in the visible alignment
- */
- public int findColumnPosition(int hiddenColumn)
- {
- int result = hiddenColumn;
- if (hiddenColumns != null)
- {
- int index = 0;
- int[] region;
- do
- {
- region = hiddenColumns.elementAt(index++);
- if (hiddenColumn > region[1])
- {
- result -= region[1] + 1 - region[0];
- }
- } while ((hiddenColumn > region[1]) && (index < hiddenColumns.size()));
-
- if (hiddenColumn >= region[0] && hiddenColumn <= region[1])
- {
- // Here the hidden column is within a region, so
- // we want to return the position of region[0]-1, adjusted for any
- // earlier hidden columns.
- // Calculate the difference between the actual hidden col position
- // and region[0]-1, and then subtract from result to convert result from
- // the adjusted hiddenColumn value to the adjusted region[0]-1 value
-
- // However, if the region begins at 0 we cannot return region[0]-1
- // just return 0
- if (region[0] == 0)
- {
- return 0;
- }
- else
- {
- return result - (hiddenColumn - region[0] + 1);
- }
- }
- }
- return result; // return the shifted position after removing hidden columns.
- }
-
- /**
- * Find the visible column which is a given visible number of columns to the
- * left of another visible column. i.e. for a startColumn x, the column which
- * is distance 1 away will be column x-1.
- *
- * @param visibleDistance
- * the number of visible columns to offset by
- * @param startColumn
- * the column to start from
- * @return the position of the column in the visible alignment
- */
- public int subtractVisibleColumns(int visibleDistance, int startColumn)
- {
- int distance = visibleDistance;
-
- // in case startColumn is in a hidden region, move it to the left
- int start = adjustForHiddenColumns(findColumnPosition(startColumn));
-
- // get index of hidden region to left of start
- int index = getHiddenIndexLeft(start);
- if (index == -1)
- {
- // no hidden regions to left of startColumn
- return start - distance;
- }
-
- // walk backwards through the alignment subtracting the counts of visible
- // columns from distance
- int[] region;
- int gap = 0;
- int nextstart = start;
-
- while ((index > -1) && (distance - gap > 0))
- {
- // subtract the gap to right of region from distance
- distance -= gap;
- start = nextstart;
-
- // calculate the next gap
- region = hiddenColumns.get(index);
- gap = start - region[1];
-
- // set start to just to left of current region
- nextstart = region[0] - 1;
- index--;
- }
-
- if (distance - gap > 0)
- {
- // fell out of loop because there are no more hidden regions
- distance -= gap;
- return nextstart - distance;
- }
- return start - distance;
-
- }
-
- /**
- * Use this method to determine where the next hiddenRegion starts
- *
- * @param hiddenRegion
- * index of hidden region (counts from 0)
- * @return column number in visible view
- */
- public int findHiddenRegionPosition(int hiddenRegion)
- {
- int result = 0;
- if (hiddenColumns != null)
- {
- int index = 0;
- int gaps = 0;
- do
- {
- int[] region = hiddenColumns.elementAt(index);
- if (hiddenRegion == 0)
- {
- return region[0];
- }
-
- gaps += region[1] + 1 - region[0];
- result = region[1] + 1;
- index++;
- } while (index <= hiddenRegion);
-
- result -= gaps;
- }
-
- return result;
- }
-
- /**
- * THis method returns the rightmost limit of a region of an alignment with
- * hidden columns. In otherwords, the next hidden column.
- *
- * @param index
- * int
- */
- public int getHiddenBoundaryRight(int alPos)
- {
- if (hiddenColumns != null)
- {
- int index = 0;
- do
- {
- int[] region = hiddenColumns.elementAt(index);
- if (alPos < region[0])
- {
- return region[0];
- }
-
- index++;
- } while (index < hiddenColumns.size());
- }
-
- return alPos;
-
- }
-
- /**
- * This method returns the leftmost limit of a region of an alignment with
- * hidden columns. In otherwords, the previous hidden column.
- *
- * @param index
- * int
- */
- public int getHiddenBoundaryLeft(int alPos)
- {
- if (hiddenColumns != null)
- {
- int index = hiddenColumns.size() - 1;
- do
- {
- int[] region = hiddenColumns.elementAt(index);
- if (alPos > region[1])
- {
- return region[1];
- }
-
- index--;
- } while (index > -1);
- }
-
- return alPos;
-
- }
-
- /**
- * This method returns the index of the hidden region to the left of a column
- * position. If the column is in a hidden region it returns the index of the
- * region to the left. If there is no hidden region to the left it returns -1.
- *
- * @param pos
- * int
- */
- private int getHiddenIndexLeft(int pos)
- {
- if (hiddenColumns != null)
- {
- int index = hiddenColumns.size() - 1;
- do
- {
- int[] region = hiddenColumns.elementAt(index);
- if (pos > region[1])
- {
- return index;
- }
-
- index--;
- } while (index > -1);
- }
-
- return -1;
-
- }
-
- public void hideSelectedColumns()
- {
- synchronized (selection)
- {
- for (int[] selregions : selection.getRanges())
- {
- hideColumns(selregions[0], selregions[1]);
- }
- selection.clear();
- }
-
- }
-
- /**
- * Adds the specified column range to the hidden columns
- *
- * @param start
- * @param end
- */
- public void hideColumns(int start, int end)
- {
- if (hiddenColumns == null)
- {
- hiddenColumns = new Vector<int[]>();
- }
-
- /*
- * traverse existing hidden ranges and insert / amend / append as
- * appropriate
- */
- for (int i = 0; i < hiddenColumns.size(); i++)
- {
- int[] region = hiddenColumns.elementAt(i);
-
- if (end < region[0] - 1)
- {
- /*
- * insert discontiguous preceding range
- */
- hiddenColumns.insertElementAt(new int[] { start, end }, i);
- return;
- }
-
- if (end <= region[1])
- {
- /*
- * new range overlaps existing, or is contiguous preceding it - adjust
- * start column
- */
- region[0] = Math.min(region[0], start);
- return;
- }
-
- if (start <= region[1] + 1)
- {
- /*
- * new range overlaps existing, or is contiguous following it - adjust
- * start and end columns
- */
- region[0] = Math.min(region[0], start);
- region[1] = Math.max(region[1], end);
-
- /*
- * also update or remove any subsequent ranges
- * that are overlapped
- */
- while (i < hiddenColumns.size() - 1)
- {
- int[] nextRegion = hiddenColumns.get(i + 1);
- if (nextRegion[0] > end + 1)
- {
- /*
- * gap to next hidden range - no more to update
- */
- break;
- }
- region[1] = Math.max(nextRegion[1], end);
- hiddenColumns.remove(i + 1);
- }
- return;
- }
- }
-
- /*
- * remaining case is that the new range follows everything else
- */
- hiddenColumns.addElement(new int[] { start, end });
- }
-
- /**
- * Hides the specified column and any adjacent selected columns
- *
- * @param res
- * int
- */
- public void hideColumns(int col)
- {
- /*
- * deselect column (whether selected or not!)
- */
- removeElement(col);
-
- /*
- * find adjacent selected columns
- */
- int min = col - 1, max = col + 1;
- while (contains(min))
- {
- removeElement(min);
- min--;
- }
-
- while (contains(max))
- {
- removeElement(max);
- max++;
- }
-
- /*
- * min, max are now the closest unselected columns
- */
- min++;
- max--;
- if (min > max)
- {
- min = max;
- }
-
- hideColumns(min, max);
- }
-
- /**
- * Unhides, and adds to the selection list, all hidden columns
- */
- public void revealAllHiddenColumns()
- {
- if (hiddenColumns != null)
- {
- for (int i = 0; i < hiddenColumns.size(); i++)
- {
- int[] region = hiddenColumns.elementAt(i);
- for (int j = region[0]; j < region[1] + 1; j++)
- {
- addElement(j);
- }
- }
- }
-
- hiddenColumns = null;
- }
-
- /**
- * Reveals, and marks as selected, the hidden column range with the given
- * start column
- *
- * @param start
- */
- public void revealHiddenColumns(int start)
- {
- for (int i = 0; i < hiddenColumns.size(); i++)
- {
- int[] region = hiddenColumns.elementAt(i);
- if (start == region[0])
- {
- for (int j = region[0]; j < region[1] + 1; j++)
- {
- addElement(j);
- }
-
- hiddenColumns.removeElement(region);
- break;
- }
- }
- if (hiddenColumns.size() == 0)
- {
- hiddenColumns = null;
- }
- }
-
- public boolean isVisible(int column)
- {
- if (hiddenColumns != null)
- {
- for (int[] region : hiddenColumns)
- {
- if (column >= region[0] && column <= region[1])
- {
- return false;
- }
- }
- }
-
- return true;
- }
-
- /**
- * Copy constructor
- *
- * @param copy
- */
- public ColumnSelection(ColumnSelection copy)
- {
- if (copy != null)
- {
- selection = new IntList(copy.selection);
- if (copy.hiddenColumns != null)
- {
- hiddenColumns = new Vector<int[]>(copy.hiddenColumns.size());
- for (int i = 0, j = copy.hiddenColumns.size(); i < j; i++)
- {
- int[] rh, cp;
- rh = copy.hiddenColumns.elementAt(i);
- if (rh != null)
- {
- cp = new int[rh.length];
- System.arraycopy(rh, 0, cp, 0, rh.length);
- hiddenColumns.addElement(cp);
- }
- }
- }
- }
- }
-
- /**
- * ColumnSelection
+ *
+ * @param col
+ * index to search for in column selection
+ *
+ * @return true if col is selected
*/
- public ColumnSelection()
+ public boolean contains(int col)
{
+ return (col > -1) ? selection.isSelected(col) : false;
}
- public String[] getVisibleSequenceStrings(int start, int end,
- SequenceI[] seqs)
+ /**
+ * Answers true if no columns are selected, else false
+ */
+ public boolean isEmpty()
{
- int i, iSize = seqs.length;
- String selections[] = new String[iSize];
- if (hiddenColumns != null && hiddenColumns.size() > 0)
- {
- for (i = 0; i < iSize; i++)
- {
- StringBuffer visibleSeq = new StringBuffer();
- List<int[]> regions = getHiddenColumns();
-
- int blockStart = start, blockEnd = end;
- int[] region;
- int hideStart, hideEnd;
-
- for (int j = 0; j < regions.size(); j++)
- {
- region = regions.get(j);
- hideStart = region[0];
- hideEnd = region[1];
-
- if (hideStart < start)
- {
- continue;
- }
-
- blockStart = Math.min(blockStart, hideEnd + 1);
- blockEnd = Math.min(blockEnd, hideStart);
-
- if (blockStart > blockEnd)
- {
- break;
- }
-
- visibleSeq.append(seqs[i].getSequence(blockStart, blockEnd));
-
- blockStart = hideEnd + 1;
- blockEnd = end;
- }
-
- if (end > blockStart)
- {
- visibleSeq.append(seqs[i].getSequence(blockStart, end));
- }
+ return selection == null || selection.isEmpty();
+ }
- selections[i] = visibleSeq.toString();
- }
- }
- else
+ /**
+ * rightmost selected column
+ *
+ * @return rightmost column in alignment that is selected
+ */
+ public int getMax()
+ {
+ if (selection.isEmpty())
{
- for (i = 0; i < iSize; i++)
- {
- selections[i] = seqs[i].getSequenceAsString(start, end);
- }
+ return -1;
}
-
- return selections;
+ return selection.getMaxColumn();
}
/**
- * return all visible segments between the given start and end boundaries
+ * Leftmost column in selection
*
- * @param start
- * (first column inclusive from 0)
- * @param end
- * (last column - not inclusive)
- * @return int[] {i_start, i_end, ..} where intervals lie in
- * start<=i_start<=i_end<end
+ * @return column index of leftmost column in selection
*/
- public int[] getVisibleContigs(int start, int end)
+ public int getMin()
{
- if (hiddenColumns != null && hiddenColumns.size() > 0)
+ if (selection.isEmpty())
{
- List<int[]> visiblecontigs = new ArrayList<int[]>();
- List<int[]> regions = getHiddenColumns();
-
- int vstart = start;
- int[] region;
- int hideStart, hideEnd;
-
- for (int j = 0; vstart < end && j < regions.size(); j++)
- {
- region = regions.get(j);
- hideStart = region[0];
- hideEnd = region[1];
-
- if (hideEnd < vstart)
- {
- continue;
- }
- if (hideStart > vstart)
- {
- visiblecontigs.add(new int[] { vstart, hideStart - 1 });
- }
- vstart = hideEnd + 1;
- }
+ return 1000000000;
+ }
+ return selection.getMinColumn();
+ }
- if (vstart < end)
- {
- visiblecontigs.add(new int[] { vstart, end - 1 });
- }
- int[] vcontigs = new int[visiblecontigs.size() * 2];
- for (int i = 0, j = visiblecontigs.size(); i < j; i++)
+ public void hideSelectedColumns(AlignmentI al)
+ {
+ synchronized (selection)
+ {
+ for (int[] selregions : selection.getRanges())
{
- int[] vc = visiblecontigs.get(i);
- visiblecontigs.set(i, null);
- vcontigs[i * 2] = vc[0];
- vcontigs[i * 2 + 1] = vc[1];
+ al.getHiddenColumns().hideColumns(selregions[0], selregions[1]);
}
- visiblecontigs.clear();
- return vcontigs;
- }
- else
- {
- return new int[] { start, end - 1 };
+ selection.clear();
}
+
}
+
/**
- * Locate the first and last position visible for this sequence. if seq isn't
- * visible then return the position of the left and right of the hidden
- * boundary region, and the corresponding alignment column indices for the
- * extent of the sequence
+ * Hides the specified column and any adjacent selected columns
*
- * @param seq
- * @return int[] { visible start, visible end, first seqpos, last seqpos,
- * alignment index for seq start, alignment index for seq end }
+ * @param res
+ * int
*/
- public int[] locateVisibleBoundsOfSequence(SequenceI seq)
+ public void hideSelectedColumns(int col, HiddenColumns hidden)
{
- int fpos = seq.getStart(), lpos = seq.getEnd();
- int start = 0;
+ /*
+ * deselect column (whether selected or not!)
+ */
+ removeElement(col);
- if (hiddenColumns == null || hiddenColumns.size() == 0)
+ /*
+ * find adjacent selected columns
+ */
+ int min = col - 1, max = col + 1;
+ while (contains(min))
{
- int ifpos = seq.findIndex(fpos) - 1, ilpos = seq.findIndex(lpos) - 1;
- return new int[] { ifpos, ilpos, fpos, lpos, ifpos, ilpos };
+ removeElement(min);
+ min--;
}
- // Simply walk along the sequence whilst watching for hidden column
- // boundaries
- List<int[]> regions = getHiddenColumns();
- int spos = fpos, lastvispos = -1, rcount = 0, hideStart = seq
- .getLength(), hideEnd = -1;
- int visPrev = 0, visNext = 0, firstP = -1, lastP = -1;
- boolean foundStart = false;
- for (int p = 0, pLen = seq.getLength(); spos <= seq.getEnd()
- && p < pLen; p++)
+ while (contains(max))
{
- if (!Comparison.isGap(seq.getCharAt(p)))
- {
- // keep track of first/last column
- // containing sequence data regardless of visibility
- if (firstP == -1)
- {
- firstP = p;
- }
- lastP = p;
- // update hidden region start/end
- while (hideEnd < p && rcount < regions.size())
- {
- int[] region = regions.get(rcount++);
- visPrev = visNext;
- visNext += region[0] - visPrev;
- hideStart = region[0];
- hideEnd = region[1];
- }
- if (hideEnd < p)
- {
- hideStart = seq.getLength();
- }
- // update visible boundary for sequence
- if (p < hideStart)
- {
- if (!foundStart)
- {
- fpos = spos;
- start = p;
- foundStart = true;
- }
- lastvispos = p;
- lpos = spos;
- }
- // look for next sequence position
- spos++;
- }
+ removeElement(max);
+ max++;
}
- if (foundStart)
+
+ /*
+ * min, max are now the closest unselected columns
+ */
+ min++;
+ max--;
+ if (min > max)
{
- return new int[] { findColumnPosition(start),
- findColumnPosition(lastvispos), fpos, lpos, firstP, lastP };
+ min = max;
}
- // otherwise, sequence was completely hidden
- return new int[] { visPrev, visNext, 0, 0, firstP, lastP };
+
+ hidden.hideColumns(min, max);
}
+
+
+
+
/**
- * delete any columns in alignmentAnnotation that are hidden (including
- * sequence associated annotation).
+ * Copy constructor
*
- * @param alignmentAnnotation
+ * @param copy
*/
- public void makeVisibleAnnotation(AlignmentAnnotation alignmentAnnotation)
+ public ColumnSelection(ColumnSelection copy)
{
- makeVisibleAnnotation(-1, -1, alignmentAnnotation);
+ if (copy != null)
+ {
+ selection = new IntList(copy.selection);
+ }
}
/**
- * delete any columns in alignmentAnnotation that are hidden (including
- * sequence associated annotation).
- *
- * @param start
- * remove any annotation to the right of this column
- * @param end
- * remove any annotation to the left of this column
- * @param alignmentAnnotation
- * the annotation to operate on
+ * ColumnSelection
*/
- public void makeVisibleAnnotation(int start, int end,
- AlignmentAnnotation alignmentAnnotation)
+ public ColumnSelection()
{
- if (alignmentAnnotation.annotations == null)
- {
- return;
- }
- if (start == end && end == -1)
- {
- start = 0;
- end = alignmentAnnotation.annotations.length;
- }
- if (hiddenColumns != null && hiddenColumns.size() > 0)
- {
- // then mangle the alignmentAnnotation annotation array
- Vector<Annotation[]> annels = new Vector<Annotation[]>();
- Annotation[] els = null;
- List<int[]> regions = getHiddenColumns();
- int blockStart = start, blockEnd = end;
- int[] region;
- int hideStart, hideEnd, w = 0;
-
- for (int j = 0; j < regions.size(); j++)
- {
- region = regions.get(j);
- hideStart = region[0];
- hideEnd = region[1];
-
- if (hideStart < start)
- {
- continue;
- }
-
- blockStart = Math.min(blockStart, hideEnd + 1);
- blockEnd = Math.min(blockEnd, hideStart);
+ }
- if (blockStart > blockEnd)
- {
- break;
- }
- annels.addElement(els = new Annotation[blockEnd - blockStart]);
- System.arraycopy(alignmentAnnotation.annotations, blockStart, els,
- 0, els.length);
- w += els.length;
- blockStart = hideEnd + 1;
- blockEnd = end;
- }
- if (end > blockStart)
- {
- annels.addElement(els = new Annotation[end - blockStart + 1]);
- if ((els.length + blockStart) <= alignmentAnnotation.annotations.length)
- {
- // copy just the visible segment of the annotation row
- System.arraycopy(alignmentAnnotation.annotations, blockStart,
- els, 0, els.length);
- }
- else
- {
- // copy to the end of the annotation row
- System.arraycopy(alignmentAnnotation.annotations, blockStart,
- els, 0,
- (alignmentAnnotation.annotations.length - blockStart));
- }
- w += els.length;
- }
- if (w == 0)
- {
- return;
- }
- alignmentAnnotation.annotations = new Annotation[w];
- w = 0;
- for (Annotation[] chnk : annels)
- {
- System.arraycopy(chnk, 0, alignmentAnnotation.annotations, w,
- chnk.length);
- w += chnk.length;
- }
- }
- else
- {
- alignmentAnnotation.restrict(start, end);
- }
- }
/**
* Invert the column selection from first to end-1. leaves hiddenColumns
* @param first
* @param end
*/
- public void invertColumnSelection(int first, int width)
+ public void invertColumnSelection(int first, int width, AlignmentI al)
{
- boolean hasHidden = hiddenColumns != null && hiddenColumns.size() > 0;
+ boolean hasHidden = al.getHiddenColumns().hasHidden();
for (int i = first; i < width; i++)
{
if (contains(i))
}
else
{
- if (!hasHidden || isVisible(i))
+ if (!hasHidden || al.getHiddenColumns().isVisible(i))
{
addElement(i);
}
}
/**
- * add in any unselected columns from the given column selection, excluding
- * any that are hidden.
- *
- * @param colsel
- */
- public void addElementsFrom(ColumnSelection colsel)
- {
- if (colsel != null && !colsel.isEmpty())
- {
- for (Integer col : colsel.getSelected())
- {
- if (hiddenColumns != null && isVisible(col.intValue()))
- {
- selection.add(col);
- }
- }
- }
- }
-
- /**
- * set the selected columns the given column selection, excluding any columns
- * that are hidden.
+ * set the selected columns to the given column selection, excluding any
+ * columns that are hidden.
*
* @param colsel
*/
- public void setElementsFrom(ColumnSelection colsel)
+ public void setElementsFrom(ColumnSelection colsel,
+ HiddenColumns hiddenColumns)
{
selection = new IntList();
if (colsel.selection != null && colsel.selection.size() > 0)
{
- if (hiddenColumns != null && hiddenColumns.size() > 0)
+ if (hiddenColumns.hasHidden())
{
// only select visible columns in this columns selection
- addElementsFrom(colsel);
- }
- else
- {
- // add everything regardless
for (Integer col : colsel.getSelected())
{
- addElement(col);
- }
- }
- }
- }
-
- /**
- * Add gaps into the sequences aligned to profileseq under the given
- * AlignmentView
- *
- * @param profileseq
- * @param al
- * - alignment to have gaps inserted into it
- * @param input
- * - alignment view where sequence corresponding to profileseq is
- * first entry
- * @return new Column selection for new alignment view, with insertions into
- * profileseq marked as hidden.
- */
- public static ColumnSelection propagateInsertions(SequenceI profileseq,
- AlignmentI al, AlignmentView input)
- {
- int profsqpos = 0;
-
- // return propagateInsertions(profileseq, al, )
- char gc = al.getGapCharacter();
- Object[] alandcolsel = input.getAlignmentAndColumnSelection(gc);
- ColumnSelection nview = (ColumnSelection) alandcolsel[1];
- SequenceI origseq = ((SequenceI[]) alandcolsel[0])[profsqpos];
- nview.propagateInsertions(profileseq, al, origseq);
- return nview;
- }
-
- /**
- *
- * @param profileseq
- * - sequence in al which corresponds to origseq
- * @param al
- * - alignment which is to have gaps inserted into it
- * @param origseq
- * - sequence corresponding to profileseq which defines gap map for
- * modifying al
- */
- public void propagateInsertions(SequenceI profileseq, AlignmentI al,
- SequenceI origseq)
- {
- char gc = al.getGapCharacter();
- // recover mapping between sequence's non-gap positions and positions
- // mapping to view.
- pruneDeletions(ShiftList.parseMap(origseq.gapMap()));
- int[] viscontigs = getVisibleContigs(0, profileseq.getLength());
- int spos = 0;
- int offset = 0;
- // input.pruneDeletions(ShiftList.parseMap(((SequenceI[])
- // alandcolsel[0])[0].gapMap()))
- // add profile to visible contigs
- for (int v = 0; v < viscontigs.length; v += 2)
- {
- if (viscontigs[v] > spos)
- {
- StringBuffer sb = new StringBuffer();
- for (int s = 0, ns = viscontigs[v] - spos; s < ns; s++)
- {
- sb.append(gc);
- }
- for (int s = 0, ns = al.getHeight(); s < ns; s++)
- {
- SequenceI sqobj = al.getSequenceAt(s);
- if (sqobj != profileseq)
+ if (hiddenColumns != null
+ && hiddenColumns.isVisible(col.intValue()))
{
- String sq = al.getSequenceAt(s).getSequenceAsString();
- if (sq.length() <= spos + offset)
- {
- // pad sequence
- int diff = spos + offset - sq.length() - 1;
- if (diff > 0)
- {
- // pad gaps
- sq = sq + sb;
- while ((diff = spos + offset - sq.length() - 1) > 0)
- {
- // sq = sq
- // + ((diff >= sb.length()) ? sb.toString() : sb
- // .substring(0, diff));
- if (diff >= sb.length())
- {
- sq += sb.toString();
- }
- else
- {
- char[] buf = new char[diff];
- sb.getChars(0, diff, buf, 0);
- sq += buf.toString();
- }
- }
- }
- sq += sb.toString();
- }
- else
- {
- al.getSequenceAt(s).setSequence(
- sq.substring(0, spos + offset) + sb.toString()
- + sq.substring(spos + offset));
- }
+ selection.add(col);
}
}
- // offset+=sb.length();
- }
- spos = viscontigs[v + 1] + 1;
- }
- if ((offset + spos) < profileseq.getLength())
- {
- // pad the final region with gaps.
- StringBuffer sb = new StringBuffer();
- for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++)
- {
- sb.append(gc);
}
- for (int s = 0, ns = al.getHeight(); s < ns; s++)
+ else
{
- SequenceI sqobj = al.getSequenceAt(s);
- if (sqobj == profileseq)
- {
- continue;
- }
- String sq = sqobj.getSequenceAsString();
- // pad sequence
- int diff = origseq.getLength() - sq.length();
- while (diff > 0)
+ // add everything regardless
+ for (Integer col : colsel.getSelected())
{
- // sq = sq
- // + ((diff >= sb.length()) ? sb.toString() : sb
- // .substring(0, diff));
- if (diff >= sb.length())
- {
- sq += sb.toString();
- }
- else
- {
- char[] buf = new char[diff];
- sb.getChars(0, diff, buf, 0);
- sq += buf.toString();
- }
- diff = origseq.getLength() - sq.length();
+ addElement(col);
}
}
}
}
+
/**
*
* @return true if there are columns marked
return (selection != null && selection.size() > 0);
}
- /**
- *
- * @return true if there are columns hidden
- */
- public boolean hasHiddenColumns()
- {
- return hiddenColumns != null && hiddenColumns.size() > 0;
- }
-
- /**
- *
- * @return true if there are more than one set of columns hidden
- */
- public boolean hasManyHiddenColumns()
- {
- return hiddenColumns != null && hiddenColumns.size() > 1;
- }
- /**
- * mark the columns corresponding to gap characters as hidden in the column
- * selection
- *
- * @param sr
- */
- public void hideInsertionsFor(SequenceI sr)
- {
- List<int[]> inserts = sr.getInsertions();
- for (int[] r : inserts)
- {
- hideColumns(r[0], r[1]);
- }
- }
public boolean filterAnnotations(Annotation[] annotations,
AnnotationFilterParameter filterParams)
{
// JBPNote - this method needs to be refactored to become independent of
// viewmodel package
- this.revealAllHiddenColumns();
this.clear();
int count = 0;
do
}
/**
- * Returns a hashCode built from selected columns and hidden column ranges
+ * Returns a hashCode built from selected columns ranges
*/
@Override
public int hashCode()
{
- int hashCode = selection.hashCode();
- if (hiddenColumns != null)
- {
- for (int[] hidden : hiddenColumns)
- {
- hashCode = 31 * hashCode + hidden[0];
- hashCode = 31 * hashCode + hidden[1];
- }
- }
- return hashCode;
+ return selection.hashCode();
}
/**
return false;
}
- /*
- * check hidden columns are either both null, or match
- */
- if (this.hiddenColumns == null)
- {
- return (that.hiddenColumns == null);
- }
- if (that.hiddenColumns == null
- || that.hiddenColumns.size() != this.hiddenColumns.size())
- {
- return false;
- }
- int i = 0;
- for (int[] thisRange : hiddenColumns)
- {
- int[] thatRange = that.hiddenColumns.get(i++);
- if (thisRange[0] != thatRange[0] || thisRange[1] != thatRange[1])
- {
- return false;
- }
- }
return true;
}
--- /dev/null
+package jalview.datamodel;
+
+import jalview.util.Comparison;
+import jalview.util.ShiftList;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Vector;
+
+public class HiddenColumns
+{
+ /*
+ * list of hidden column [start, end] ranges; the list is maintained in
+ * ascending start column order
+ */
+ private Vector<int[]> hiddenColumns;
+
+ /**
+ * This Method is used to return all the HiddenColumn regions
+ *
+ * @return empty list or List of hidden column intervals
+ */
+ public List<int[]> getHiddenRegions()
+ {
+ return hiddenColumns == null ? Collections.<int[]> emptyList()
+ : hiddenColumns;
+ }
+
+ /**
+ * Find the number of hidden columns
+ *
+ * @return number of hidden columns
+ */
+ public int getSize()
+ {
+ int size = 0;
+ if (hasHidden())
+ {
+ for (int[] range : hiddenColumns)
+ {
+ size += range[1] - range[0] + 1;
+ }
+ }
+ return size;
+ }
+
+ /**
+ * Answers if there are any hidden columns
+ *
+ * @return true if there are hidden columns
+ */
+ public boolean hasHidden()
+ {
+ return (hiddenColumns != null) && (!hiddenColumns.isEmpty());
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (!(obj instanceof HiddenColumns))
+ {
+ return false;
+ }
+ HiddenColumns that = (HiddenColumns) obj;
+
+ /*
+ * check hidden columns are either both null, or match
+ */
+ if (this.hiddenColumns == null)
+ {
+ return (that.hiddenColumns == null);
+ }
+ if (that.hiddenColumns == null
+ || that.hiddenColumns.size() != this.hiddenColumns.size())
+ {
+ return false;
+ }
+ int i = 0;
+ for (int[] thisRange : hiddenColumns)
+ {
+ int[] thatRange = that.hiddenColumns.get(i++);
+ if (thisRange[0] != thatRange[0] || thisRange[1] != thatRange[1])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Return absolute column index for a visible column index
+ *
+ * @param column
+ * int column index in alignment view (count from zero)
+ * @return alignment column index for column
+ */
+ public int adjustForHiddenColumns(int column)
+ {
+ int result = column;
+ if (hiddenColumns != null)
+ {
+ for (int i = 0; i < hiddenColumns.size(); i++)
+ {
+ int[] region = hiddenColumns.elementAt(i);
+ if (result >= region[0])
+ {
+ result += region[1] - region[0] + 1;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Use this method to find out where a column will appear in the visible
+ * alignment when hidden columns exist. If the column is not visible, then the
+ * left-most visible column will always be returned.
+ *
+ * @param hiddenColumn
+ * the column index in the full alignment including hidden columns
+ * @return the position of the column in the visible alignment
+ */
+ public int findColumnPosition(int hiddenColumn)
+ {
+ int result = hiddenColumn;
+ if (hiddenColumns != null)
+ {
+ int index = 0;
+ int[] region;
+ do
+ {
+ region = hiddenColumns.elementAt(index++);
+ if (hiddenColumn > region[1])
+ {
+ result -= region[1] + 1 - region[0];
+ }
+ } while ((hiddenColumn > region[1]) && (index < hiddenColumns.size()));
+
+ if (hiddenColumn >= region[0] && hiddenColumn <= region[1])
+ {
+ // Here the hidden column is within a region, so
+ // we want to return the position of region[0]-1, adjusted for any
+ // earlier hidden columns.
+ // Calculate the difference between the actual hidden col position
+ // and region[0]-1, and then subtract from result to convert result from
+ // the adjusted hiddenColumn value to the adjusted region[0]-1 value
+
+ // However, if the region begins at 0 we cannot return region[0]-1
+ // just return 0
+ if (region[0] == 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return result - (hiddenColumn - region[0] + 1);
+ }
+ }
+ }
+ return result; // return the shifted position after removing hidden columns.
+ }
+
+ /**
+ * Find the visible column which is a given visible number of columns to the
+ * left of another visible column. i.e. for a startColumn x, the column which
+ * is distance 1 away will be column x-1.
+ *
+ * @param visibleDistance
+ * the number of visible columns to offset by
+ * @param startColumn
+ * the column to start from
+ * @return the position of the column in the visible alignment
+ */
+ public int subtractVisibleColumns(int visibleDistance, int startColumn)
+ {
+ int distance = visibleDistance;
+
+ // in case startColumn is in a hidden region, move it to the left
+ int start = adjustForHiddenColumns(findColumnPosition(startColumn));
+
+ // get index of hidden region to left of start
+ int index = getHiddenIndexLeft(start);
+ if (index == -1)
+ {
+ // no hidden regions to left of startColumn
+ return start - distance;
+ }
+
+ // walk backwards through the alignment subtracting the counts of visible
+ // columns from distance
+ int[] region;
+ int gap = 0;
+ int nextstart = start;
+
+ while ((index > -1) && (distance - gap > 0))
+ {
+ // subtract the gap to right of region from distance
+ distance -= gap;
+ start = nextstart;
+
+ // calculate the next gap
+ region = hiddenColumns.get(index);
+ gap = start - region[1];
+
+ // set start to just to left of current region
+ nextstart = region[0] - 1;
+ index--;
+ }
+
+ if (distance - gap > 0)
+ {
+ // fell out of loop because there are no more hidden regions
+ distance -= gap;
+ return nextstart - distance;
+ }
+ return start - distance;
+
+ }
+
+ /**
+ * Use this method to determine where the next hiddenRegion starts
+ *
+ * @param hiddenRegion
+ * index of hidden region (counts from 0)
+ * @return column number in visible view
+ */
+ public int findHiddenRegionPosition(int hiddenRegion)
+ {
+ int result = 0;
+ if (hiddenColumns != null)
+ {
+ int index = 0;
+ int gaps = 0;
+ do
+ {
+ int[] region = hiddenColumns.elementAt(index);
+ if (hiddenRegion == 0)
+ {
+ return region[0];
+ }
+
+ gaps += region[1] + 1 - region[0];
+ result = region[1] + 1;
+ index++;
+ } while (index <= hiddenRegion);
+
+ result -= gaps;
+ }
+
+ return result;
+ }
+
+ /**
+ * This method returns the rightmost limit of a region of an alignment with
+ * hidden columns. In otherwords, the next hidden column.
+ *
+ * @param index
+ * int
+ */
+ public int getHiddenBoundaryRight(int alPos)
+ {
+ if (hiddenColumns != null)
+ {
+ int index = 0;
+ do
+ {
+ int[] region = hiddenColumns.elementAt(index);
+ if (alPos < region[0])
+ {
+ return region[0];
+ }
+
+ index++;
+ } while (index < hiddenColumns.size());
+ }
+
+ return alPos;
+
+ }
+
+ /**
+ * This method returns the leftmost limit of a region of an alignment with
+ * hidden columns. In otherwords, the previous hidden column.
+ *
+ * @param index
+ * int
+ */
+ public int getHiddenBoundaryLeft(int alPos)
+ {
+ if (hiddenColumns != null)
+ {
+ int index = hiddenColumns.size() - 1;
+ do
+ {
+ int[] region = hiddenColumns.elementAt(index);
+ if (alPos > region[1])
+ {
+ return region[1];
+ }
+
+ index--;
+ } while (index > -1);
+ }
+
+ return alPos;
+
+ }
+
+ /**
+ * This method returns the index of the hidden region to the left of a column
+ * position. If the column is in a hidden region it returns the index of the
+ * region to the left. If there is no hidden region to the left it returns -1.
+ *
+ * @param pos
+ * int
+ */
+ private int getHiddenIndexLeft(int pos)
+ {
+ if (hiddenColumns != null)
+ {
+ int index = hiddenColumns.size() - 1;
+ do
+ {
+ int[] region = hiddenColumns.elementAt(index);
+ if (pos > region[1])
+ {
+ return index;
+ }
+
+ index--;
+ } while (index > -1);
+ }
+
+ return -1;
+
+ }
+
+ /**
+ * Adds the specified column range to the hidden columns
+ *
+ * @param start
+ * @param end
+ */
+ public void hideColumns(int start, int end)
+ {
+ if (hiddenColumns == null)
+ {
+ hiddenColumns = new Vector<int[]>();
+ }
+
+ /*
+ * traverse existing hidden ranges and insert / amend / append as
+ * appropriate
+ */
+ for (int i = 0; i < hiddenColumns.size(); i++)
+ {
+ int[] region = hiddenColumns.elementAt(i);
+
+ if (end < region[0] - 1)
+ {
+ /*
+ * insert discontiguous preceding range
+ */
+ hiddenColumns.insertElementAt(new int[] { start, end }, i);
+ return;
+ }
+
+ if (end <= region[1])
+ {
+ /*
+ * new range overlaps existing, or is contiguous preceding it - adjust
+ * start column
+ */
+ region[0] = Math.min(region[0], start);
+ return;
+ }
+
+ if (start <= region[1] + 1)
+ {
+ /*
+ * new range overlaps existing, or is contiguous following it - adjust
+ * start and end columns
+ */
+ region[0] = Math.min(region[0], start);
+ region[1] = Math.max(region[1], end);
+
+ /*
+ * also update or remove any subsequent ranges
+ * that are overlapped
+ */
+ while (i < hiddenColumns.size() - 1)
+ {
+ int[] nextRegion = hiddenColumns.get(i + 1);
+ if (nextRegion[0] > end + 1)
+ {
+ /*
+ * gap to next hidden range - no more to update
+ */
+ break;
+ }
+ region[1] = Math.max(nextRegion[1], end);
+ hiddenColumns.remove(i + 1);
+ }
+ return;
+ }
+ }
+
+ /*
+ * remaining case is that the new range follows everything else
+ */
+ hiddenColumns.addElement(new int[] { start, end });
+ }
+
+ public boolean isVisible(int column)
+ {
+ if (hiddenColumns != null)
+ {
+ for (int[] region : hiddenColumns)
+ {
+ if (column >= region[0] && column <= region[1])
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * ColumnSelection
+ */
+ public HiddenColumns()
+ {
+ }
+
+ /**
+ * Copy constructor
+ *
+ * @param copy
+ */
+ public HiddenColumns(HiddenColumns copy)
+ {
+ if (copy != null)
+ {
+ if (copy.hiddenColumns != null)
+ {
+ hiddenColumns = new Vector<int[]>(copy.hiddenColumns.size());
+ for (int i = 0, j = copy.hiddenColumns.size(); i < j; i++)
+ {
+ int[] rh, cp;
+ rh = copy.hiddenColumns.elementAt(i);
+ if (rh != null)
+ {
+ cp = new int[rh.length];
+ System.arraycopy(rh, 0, cp, 0, rh.length);
+ hiddenColumns.addElement(cp);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * propagate shift in alignment columns to column selection
+ *
+ * @param start
+ * beginning of edit
+ * @param left
+ * shift in edit (+ve for removal, or -ve for inserts)
+ */
+ public List<int[]> compensateForEdit(int start, int change,
+ ColumnSelection sel)
+ {
+ List<int[]> deletedHiddenColumns = null;
+
+ if (hiddenColumns != null)
+ {
+ deletedHiddenColumns = new ArrayList<int[]>();
+ int hSize = hiddenColumns.size();
+ for (int i = 0; i < hSize; i++)
+ {
+ int[] region = hiddenColumns.elementAt(i);
+ if (region[0] > start && start + change > region[1])
+ {
+ deletedHiddenColumns.add(region);
+
+ hiddenColumns.removeElementAt(i);
+ i--;
+ hSize--;
+ continue;
+ }
+
+ if (region[0] > start)
+ {
+ region[0] -= change;
+ region[1] -= change;
+ }
+
+ if (region[0] < 0)
+ {
+ region[0] = 0;
+ }
+
+ }
+
+ this.revealHiddenColumns(0, sel);
+ }
+
+ return deletedHiddenColumns;
+ }
+
+ /**
+ * propagate shift in alignment columns to column selection special version of
+ * compensateForEdit - allowing for edits within hidden regions
+ *
+ * @param start
+ * beginning of edit
+ * @param left
+ * shift in edit (+ve for removal, or -ve for inserts)
+ */
+ public void compensateForDelEdits(int start, int change)
+ {
+ if (hiddenColumns != null)
+ {
+ for (int i = 0; i < hiddenColumns.size(); i++)
+ {
+ int[] region = hiddenColumns.elementAt(i);
+ if (region[0] >= start)
+ {
+ region[0] -= change;
+ }
+ if (region[1] >= start)
+ {
+ region[1] -= change;
+ }
+ if (region[1] < region[0])
+ {
+ hiddenColumns.removeElementAt(i--);
+ }
+
+ if (region[0] < 0)
+ {
+ region[0] = 0;
+ }
+ if (region[1] < 0)
+ {
+ region[1] = 0;
+ }
+ }
+ }
+ }
+
+ /**
+ * return all visible segments between the given start and end boundaries
+ *
+ * @param start
+ * (first column inclusive from 0)
+ * @param end
+ * (last column - not inclusive)
+ * @return int[] {i_start, i_end, ..} where intervals lie in
+ * start<=i_start<=i_end<end
+ */
+ public int[] getVisibleContigs(int start, int end)
+ {
+ if (hiddenColumns != null && hiddenColumns.size() > 0)
+ {
+ List<int[]> visiblecontigs = new ArrayList<int[]>();
+ List<int[]> regions = getHiddenRegions();
+
+ int vstart = start;
+ int[] region;
+ int hideStart, hideEnd;
+
+ for (int j = 0; vstart < end && j < regions.size(); j++)
+ {
+ region = regions.get(j);
+ hideStart = region[0];
+ hideEnd = region[1];
+
+ if (hideEnd < vstart)
+ {
+ continue;
+ }
+ if (hideStart > vstart)
+ {
+ visiblecontigs.add(new int[] { vstart, hideStart - 1 });
+ }
+ vstart = hideEnd + 1;
+ }
+
+ if (vstart < end)
+ {
+ visiblecontigs.add(new int[] { vstart, end - 1 });
+ }
+ int[] vcontigs = new int[visiblecontigs.size() * 2];
+ for (int i = 0, j = visiblecontigs.size(); i < j; i++)
+ {
+ int[] vc = visiblecontigs.get(i);
+ visiblecontigs.set(i, null);
+ vcontigs[i * 2] = vc[0];
+ vcontigs[i * 2 + 1] = vc[1];
+ }
+ visiblecontigs.clear();
+ return vcontigs;
+ }
+ else
+ {
+ return new int[] { start, end - 1 };
+ }
+ }
+
+ public String[] getVisibleSequenceStrings(int start, int end,
+ SequenceI[] seqs)
+ {
+ int i, iSize = seqs.length;
+ String selections[] = new String[iSize];
+ if (hiddenColumns != null && hiddenColumns.size() > 0)
+ {
+ for (i = 0; i < iSize; i++)
+ {
+ StringBuffer visibleSeq = new StringBuffer();
+ List<int[]> regions = getHiddenRegions();
+
+ int blockStart = start, blockEnd = end;
+ int[] region;
+ int hideStart, hideEnd;
+
+ for (int j = 0; j < regions.size(); j++)
+ {
+ region = regions.get(j);
+ hideStart = region[0];
+ hideEnd = region[1];
+
+ if (hideStart < start)
+ {
+ continue;
+ }
+
+ blockStart = Math.min(blockStart, hideEnd + 1);
+ blockEnd = Math.min(blockEnd, hideStart);
+
+ if (blockStart > blockEnd)
+ {
+ break;
+ }
+
+ visibleSeq.append(seqs[i].getSequence(blockStart, blockEnd));
+
+ blockStart = hideEnd + 1;
+ blockEnd = end;
+ }
+
+ if (end > blockStart)
+ {
+ visibleSeq.append(seqs[i].getSequence(blockStart, end));
+ }
+
+ selections[i] = visibleSeq.toString();
+ }
+ }
+ else
+ {
+ for (i = 0; i < iSize; i++)
+ {
+ selections[i] = seqs[i].getSequenceAsString(start, end);
+ }
+ }
+
+ return selections;
+ }
+
+ /**
+ * Locate the first and last position visible for this sequence. if seq isn't
+ * visible then return the position of the left and right of the hidden
+ * boundary region, and the corresponding alignment column indices for the
+ * extent of the sequence
+ *
+ * @param seq
+ * @return int[] { visible start, visible end, first seqpos, last seqpos,
+ * alignment index for seq start, alignment index for seq end }
+ */
+ public int[] locateVisibleBoundsOfSequence(SequenceI seq)
+ {
+ int fpos = seq.getStart(), lpos = seq.getEnd();
+ int start = 0;
+
+ if (hiddenColumns == null || hiddenColumns.size() == 0)
+ {
+ int ifpos = seq.findIndex(fpos) - 1, ilpos = seq.findIndex(lpos) - 1;
+ return new int[] { ifpos, ilpos, fpos, lpos, ifpos, ilpos };
+ }
+
+ // Simply walk along the sequence whilst watching for hidden column
+ // boundaries
+ List<int[]> regions = getHiddenRegions();
+ int spos = fpos, lastvispos = -1, rcount = 0, hideStart = seq
+ .getLength(), hideEnd = -1;
+ int visPrev = 0, visNext = 0, firstP = -1, lastP = -1;
+ boolean foundStart = false;
+ for (int p = 0, pLen = seq.getLength(); spos <= seq.getEnd()
+ && p < pLen; p++)
+ {
+ if (!Comparison.isGap(seq.getCharAt(p)))
+ {
+ // keep track of first/last column
+ // containing sequence data regardless of visibility
+ if (firstP == -1)
+ {
+ firstP = p;
+ }
+ lastP = p;
+ // update hidden region start/end
+ while (hideEnd < p && rcount < regions.size())
+ {
+ int[] region = regions.get(rcount++);
+ visPrev = visNext;
+ visNext += region[0] - visPrev;
+ hideStart = region[0];
+ hideEnd = region[1];
+ }
+ if (hideEnd < p)
+ {
+ hideStart = seq.getLength();
+ }
+ // update visible boundary for sequence
+ if (p < hideStart)
+ {
+ if (!foundStart)
+ {
+ fpos = spos;
+ start = p;
+ foundStart = true;
+ }
+ lastvispos = p;
+ lpos = spos;
+ }
+ // look for next sequence position
+ spos++;
+ }
+ }
+ if (foundStart)
+ {
+ return new int[] { findColumnPosition(start),
+ findColumnPosition(lastvispos), fpos, lpos, firstP, lastP };
+ }
+ // otherwise, sequence was completely hidden
+ return new int[] { visPrev, visNext, 0, 0, firstP, lastP };
+ }
+
+ /**
+ * delete any columns in alignmentAnnotation that are hidden (including
+ * sequence associated annotation).
+ *
+ * @param alignmentAnnotation
+ */
+ public void makeVisibleAnnotation(AlignmentAnnotation alignmentAnnotation)
+ {
+ makeVisibleAnnotation(-1, -1, alignmentAnnotation);
+ }
+
+ /**
+ * delete any columns in alignmentAnnotation that are hidden (including
+ * sequence associated annotation).
+ *
+ * @param start
+ * remove any annotation to the right of this column
+ * @param end
+ * remove any annotation to the left of this column
+ * @param alignmentAnnotation
+ * the annotation to operate on
+ */
+ public void makeVisibleAnnotation(int start, int end,
+ AlignmentAnnotation alignmentAnnotation)
+ {
+ if (alignmentAnnotation.annotations == null)
+ {
+ return;
+ }
+ if (start == end && end == -1)
+ {
+ start = 0;
+ end = alignmentAnnotation.annotations.length;
+ }
+ if (hiddenColumns != null && hiddenColumns.size() > 0)
+ {
+ // then mangle the alignmentAnnotation annotation array
+ Vector<Annotation[]> annels = new Vector<Annotation[]>();
+ Annotation[] els = null;
+ List<int[]> regions = getHiddenRegions();
+ int blockStart = start, blockEnd = end;
+ int[] region;
+ int hideStart, hideEnd, w = 0;
+
+ for (int j = 0; j < regions.size(); j++)
+ {
+ region = regions.get(j);
+ hideStart = region[0];
+ hideEnd = region[1];
+
+ if (hideStart < start)
+ {
+ continue;
+ }
+
+ blockStart = Math.min(blockStart, hideEnd + 1);
+ blockEnd = Math.min(blockEnd, hideStart);
+
+ if (blockStart > blockEnd)
+ {
+ break;
+ }
+
+ annels.addElement(els = new Annotation[blockEnd - blockStart]);
+ System.arraycopy(alignmentAnnotation.annotations, blockStart, els,
+ 0, els.length);
+ w += els.length;
+ blockStart = hideEnd + 1;
+ blockEnd = end;
+ }
+
+ if (end > blockStart)
+ {
+ annels.addElement(els = new Annotation[end - blockStart + 1]);
+ if ((els.length + blockStart) <= alignmentAnnotation.annotations.length)
+ {
+ // copy just the visible segment of the annotation row
+ System.arraycopy(alignmentAnnotation.annotations, blockStart,
+ els, 0, els.length);
+ }
+ else
+ {
+ // copy to the end of the annotation row
+ System.arraycopy(alignmentAnnotation.annotations, blockStart,
+ els, 0,
+ (alignmentAnnotation.annotations.length - blockStart));
+ }
+ w += els.length;
+ }
+ if (w == 0)
+ {
+ return;
+ }
+
+ alignmentAnnotation.annotations = new Annotation[w];
+ w = 0;
+
+ for (Annotation[] chnk : annels)
+ {
+ System.arraycopy(chnk, 0, alignmentAnnotation.annotations, w,
+ chnk.length);
+ w += chnk.length;
+ }
+ }
+ else
+ {
+ alignmentAnnotation.restrict(start, end);
+ }
+ }
+
+ /**
+ *
+ * @return true if there are columns hidden
+ */
+ public boolean hasHiddenColumns()
+ {
+ return hiddenColumns != null && hiddenColumns.size() > 0;
+ }
+
+ /**
+ *
+ * @return true if there are more than one set of columns hidden
+ */
+ public boolean hasManyHiddenColumns()
+ {
+ return hiddenColumns != null && hiddenColumns.size() > 1;
+ }
+
+ /**
+ * mark the columns corresponding to gap characters as hidden in the column
+ * selection
+ *
+ * @param sr
+ */
+ public void hideInsertionsFor(SequenceI sr)
+ {
+ List<int[]> inserts = sr.getInsertions();
+ for (int[] r : inserts)
+ {
+ hideColumns(r[0], r[1]);
+ }
+ }
+
+ /**
+ * Unhides, and adds to the selection list, all hidden columns
+ */
+ public void revealAllHiddenColumns(ColumnSelection sel)
+ {
+ if (hiddenColumns != null)
+ {
+ for (int i = 0; i < hiddenColumns.size(); i++)
+ {
+ int[] region = hiddenColumns.elementAt(i);
+ for (int j = region[0]; j < region[1] + 1; j++)
+ {
+ sel.addElement(j);
+ }
+ }
+ }
+
+ hiddenColumns = null;
+ }
+
+ /**
+ * Reveals, and marks as selected, the hidden column range with the given
+ * start column
+ *
+ * @param start
+ */
+ public void revealHiddenColumns(int start, ColumnSelection sel)
+ {
+ for (int i = 0; i < hiddenColumns.size(); i++)
+ {
+ int[] region = hiddenColumns.elementAt(i);
+ if (start == region[0])
+ {
+ for (int j = region[0]; j < region[1] + 1; j++)
+ {
+ sel.addElement(j);
+ }
+
+ hiddenColumns.removeElement(region);
+ break;
+ }
+ }
+ if (hiddenColumns.size() == 0)
+ {
+ hiddenColumns = null;
+ }
+ }
+
+ /**
+ * removes intersection of position,length ranges in deletions from the
+ * start,end regions marked in intervals.
+ *
+ * @param shifts
+ * @param intervals
+ * @return
+ */
+ private boolean pruneIntervalVector(final List<int[]> shifts,
+ Vector<int[]> intervals)
+ {
+ boolean pruned = false;
+ int i = 0, j = intervals.size() - 1, s = 0, t = shifts.size() - 1;
+ int hr[] = intervals.elementAt(i);
+ int sr[] = shifts.get(s);
+ while (i <= j && s <= t)
+ {
+ boolean trailinghn = hr[1] >= sr[0];
+ if (!trailinghn)
+ {
+ if (i < j)
+ {
+ hr = intervals.elementAt(++i);
+ }
+ else
+ {
+ i++;
+ }
+ continue;
+ }
+ int endshift = sr[0] + sr[1]; // deletion ranges - -ve means an insert
+ if (endshift < hr[0] || endshift < sr[0])
+ { // leadinghc disjoint or not a deletion
+ if (s < t)
+ {
+ sr = shifts.get(++s);
+ }
+ else
+ {
+ s++;
+ }
+ continue;
+ }
+ boolean leadinghn = hr[0] >= sr[0];
+ boolean leadinghc = hr[0] < endshift;
+ boolean trailinghc = hr[1] < endshift;
+ if (leadinghn)
+ {
+ if (trailinghc)
+ { // deleted hidden region.
+ intervals.removeElementAt(i);
+ pruned = true;
+ j--;
+ if (i <= j)
+ {
+ hr = intervals.elementAt(i);
+ }
+ continue;
+ }
+ if (leadinghc)
+ {
+ hr[0] = endshift; // clip c terminal region
+ leadinghn = !leadinghn;
+ pruned = true;
+ }
+ }
+ if (!leadinghn)
+ {
+ if (trailinghc)
+ {
+ if (trailinghn)
+ {
+ hr[1] = sr[0] - 1;
+ pruned = true;
+ }
+ }
+ else
+ {
+ // sr contained in hr
+ if (s < t)
+ {
+ sr = shifts.get(++s);
+ }
+ else
+ {
+ s++;
+ }
+ continue;
+ }
+ }
+ }
+ return pruned; // true if any interval was removed or modified by
+ // operations.
+ }
+
+ /**
+ * remove any hiddenColumns or selected columns and shift remaining based on a
+ * series of position, range deletions.
+ *
+ * @param deletions
+ */
+ public void pruneDeletions(List<int[]> shifts)
+ {
+ // delete any intervals intersecting.
+ if (hiddenColumns != null)
+ {
+ pruneIntervalVector(shifts, hiddenColumns);
+ if (hiddenColumns != null && hiddenColumns.size() == 0)
+ {
+ hiddenColumns = null;
+ }
+ }
+ }
+
+ /**
+ * Add gaps into the sequences aligned to profileseq under the given
+ * AlignmentView
+ *
+ * @param profileseq
+ * @param al
+ * - alignment to have gaps inserted into it
+ * @param input
+ * - alignment view where sequence corresponding to profileseq is
+ * first entry
+ * @return new HiddenColumns for new alignment view, with insertions into
+ * profileseq marked as hidden.
+ */
+ public static HiddenColumns propagateInsertions(SequenceI profileseq,
+ AlignmentI al, AlignmentView input)
+ {
+ int profsqpos = 0;
+
+ char gc = al.getGapCharacter();
+ Object[] alandhidden = input.getAlignmentAndHiddenColumns(gc);
+ HiddenColumns nview = (HiddenColumns) alandhidden[1];
+ SequenceI origseq = ((SequenceI[]) alandhidden[0])[profsqpos];
+ nview.propagateInsertions(profileseq, al, origseq);
+ return nview;
+ }
+
+ /**
+ *
+ * @param profileseq
+ * - sequence in al which corresponds to origseq
+ * @param al
+ * - alignment which is to have gaps inserted into it
+ * @param origseq
+ * - sequence corresponding to profileseq which defines gap map for
+ * modifying al
+ */
+ private void propagateInsertions(SequenceI profileseq, AlignmentI al,
+ SequenceI origseq)
+ {
+ char gc = al.getGapCharacter();
+ // recover mapping between sequence's non-gap positions and positions
+ // mapping to view.
+ pruneDeletions(ShiftList.parseMap(origseq.gapMap()));
+ int[] viscontigs = al.getHiddenColumns().getVisibleContigs(0,
+ profileseq.getLength());
+ int spos = 0;
+ int offset = 0;
+
+ // add profile to visible contigs
+ for (int v = 0; v < viscontigs.length; v += 2)
+ {
+ if (viscontigs[v] > spos)
+ {
+ StringBuffer sb = new StringBuffer();
+ for (int s = 0, ns = viscontigs[v] - spos; s < ns; s++)
+ {
+ sb.append(gc);
+ }
+ for (int s = 0, ns = al.getHeight(); s < ns; s++)
+ {
+ SequenceI sqobj = al.getSequenceAt(s);
+ if (sqobj != profileseq)
+ {
+ String sq = al.getSequenceAt(s).getSequenceAsString();
+ if (sq.length() <= spos + offset)
+ {
+ // pad sequence
+ int diff = spos + offset - sq.length() - 1;
+ if (diff > 0)
+ {
+ // pad gaps
+ sq = sq + sb;
+ while ((diff = spos + offset - sq.length() - 1) > 0)
+ {
+ // sq = sq
+ // + ((diff >= sb.length()) ? sb.toString() : sb
+ // .substring(0, diff));
+ if (diff >= sb.length())
+ {
+ sq += sb.toString();
+ }
+ else
+ {
+ char[] buf = new char[diff];
+ sb.getChars(0, diff, buf, 0);
+ sq += buf.toString();
+ }
+ }
+ }
+ sq += sb.toString();
+ }
+ else
+ {
+ al.getSequenceAt(s).setSequence(
+ sq.substring(0, spos + offset) + sb.toString()
+ + sq.substring(spos + offset));
+ }
+ }
+ }
+ // offset+=sb.length();
+ }
+ spos = viscontigs[v + 1] + 1;
+ }
+ if ((offset + spos) < profileseq.getLength())
+ {
+ // pad the final region with gaps.
+ StringBuffer sb = new StringBuffer();
+ for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++)
+ {
+ sb.append(gc);
+ }
+ for (int s = 0, ns = al.getHeight(); s < ns; s++)
+ {
+ SequenceI sqobj = al.getSequenceAt(s);
+ if (sqobj == profileseq)
+ {
+ continue;
+ }
+ String sq = sqobj.getSequenceAsString();
+ // pad sequence
+ int diff = origseq.getLength() - sq.length();
+ while (diff > 0)
+ {
+ // sq = sq
+ // + ((diff >= sb.length()) ? sb.toString() : sb
+ // .substring(0, diff));
+ if (diff >= sb.length())
+ {
+ sq += sb.toString();
+ }
+ else
+ {
+ char[] buf = new char[diff];
+ sb.getChars(0, diff, buf, 0);
+ sq += buf.toString();
+ }
+ diff = origseq.getLength() - sq.length();
+ }
+ }
+ }
+ }
+
+ /**
+ * remove any hiddenColumns or selected columns and shift remaining based on a
+ * series of position, range deletions.
+ *
+ * @param deletions
+ */
+ private void pruneDeletions(ShiftList deletions)
+ {
+ if (deletions != null)
+ {
+ final List<int[]> shifts = deletions.getShifts();
+ if (shifts != null && shifts.size() > 0)
+ {
+ pruneDeletions(shifts);
+
+ // and shift the rest.
+ this.compensateForEdits(deletions);
+ }
+ }
+ }
+
+ /**
+ * Adjust hidden column boundaries based on a series of column additions or
+ * deletions in visible regions.
+ *
+ * @param shiftrecord
+ * @return
+ */
+ private ShiftList compensateForEdits(ShiftList shiftrecord)
+ {
+ if (shiftrecord != null)
+ {
+ final List<int[]> shifts = shiftrecord.getShifts();
+ if (shifts != null && shifts.size() > 0)
+ {
+ int shifted = 0;
+ for (int i = 0, j = shifts.size(); i < j; i++)
+ {
+ int[] sh = shifts.get(i);
+ compensateForDelEdits(shifted + sh[0], sh[1]);
+ shifted -= sh[1];
+ }
+ }
+ return shiftrecord.getInverse();
+ }
+ return null;
+ }
+
+ /**
+ * Returns a hashCode built from hidden column ranges
+ */
+ @Override
+ public int hashCode()
+ {
+ int hashCode = 1;
+ if (hiddenColumns != null)
+ {
+ for (int[] hidden : hiddenColumns)
+ {
+ hashCode = 31 * hashCode + hidden[0];
+ hashCode = 31 * hashCode + hidden[1];
+ }
+ }
+ return hashCode;
+ }
+
+}
return false;
}
+
+ /**
+ * Answers if a sequence is hidden
+ *
+ * @param seq
+ * (absolute) index to test
+ * @return true if sequence at index seq is hidden
+ */
+ public boolean isHidden(int seq)
+ {
+ if (hiddenSequences != null)
+ {
+ return (hiddenSequences[seq] != null);
+ }
+ return false;
+ }
}
/**
* create an alignment from the given array of cigar sequences and gap
* character, and marking the given segments as visible in the given
- * columselection.
+ * hiddenColumns.
*
* @param alseqs
* @param gapCharacter
- * @param colsel
- * - columnSelection where hidden regions are marked
+ * @param hidden
+ * - hiddenColumns where hidden regions are marked
* @param segments
* - visible regions of alignment
* @return SequenceI[]
*/
public static SequenceI[] createAlignmentSequences(SeqCigar[] alseqs,
- char gapCharacter, ColumnSelection colsel, int[] segments)
+ char gapCharacter, HiddenColumns hidden, int[] segments)
{
SequenceI[] seqs = new SequenceI[alseqs.length];
StringBuffer[] g_seqs = new StringBuffer[alseqs.length];
if (segments == null)
{
// add a hidden column for this deletion
- colsel.hideColumns(inspos, inspos + insert.length - 1);
+ hidden.hideColumns(inspos, inspos + insert.length - 1);
}
}
}
{
// int start=shifts.shift(segments[i]-1)+1;
// int end=shifts.shift(segments[i]+segments[i+1]-1)-1;
- colsel.hideColumns(segments[i + 1], segments[i + 1]
+ hidden.hideColumns(segments[i + 1], segments[i + 1]
+ segments[i + 2] - 1);
}
}
return aa;
}
- /**
- * Returns a list of annotations that match the specified sequenceRef, calcId
- * and label, ignoring null values.
- *
- * @return list of AlignmentAnnotation objects
- */
@Override
public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
String calcId, String label)
ArrayList<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
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))
+ if ((calcId == null || (ann.getCalcId() != null && ann.getCalcId()
+ .equals(calcId)))
+ && (seq == null || (ann.sequenceRef != null && ann.sequenceRef == seq))
+ && (label == null || (ann.label != null && ann.label
+ .equals(label))))
{
aa.add(ann);
}
public class SequenceNode extends BinaryNode
{
/** DOCUMENT ME!! */
- public float dist;
+ public double dist;
/** DOCUMENT ME!! */
public int count;
/** DOCUMENT ME!! */
- public float height;
+ public double height;
/** DOCUMENT ME!! */
public float ycount;
{
char q = name.charAt(c);
if ('0' <= q && q <= '9')
+ {
continue;
+ }
return true;
}
}
* along with Jalview. If not, see <http://www.gnu.org/licenses/>.
* The Jalview Authors are detailed in the 'AUTHORS' file.
*/
-package jalview.api.analysis;
+package jalview.datamodel;
-import jalview.api.AlignmentViewPanel;
+import jalview.api.AlignmentColsCollectionI;
-public interface ViewBasedAnalysisI
+import java.util.Iterator;
+
+public class VisibleColsCollection implements AlignmentColsCollectionI
{
+ int start;
+ int end;
+
+ HiddenColumns hidden;
+
+ public VisibleColsCollection(int s, int e, AlignmentI al)
+ {
+ start = s;
+ end = e;
+ hidden = al.getHiddenColumns();
+ }
- /**
- * Parameterise the analysis model using the current view
- *
- * @param view
- * @return true if model is applicable and calculation should proceed
- */
+ @Override
+ public Iterator<Integer> iterator()
+ {
+ return new VisibleColsIterator(start, end, hidden);
+ }
- boolean configureFromAlignmentView(AlignmentViewPanel view);
+ @Override
+ public boolean isHidden(int c)
+ {
+ return false;
+ }
}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator which iterates over all visible columns in an alignment
+ *
+ * @author kmourao
+ *
+ */
+public class VisibleColsIterator implements Iterator<Integer>
+{
+ private int last;
+
+ private int current;
+
+ private int next;
+
+ private List<int[]> hidden;
+
+ private int lasthiddenregion;
+
+ public VisibleColsIterator(int firstcol, int lastcol,
+ HiddenColumns hiddenCols)
+ {
+ last = lastcol;
+ current = firstcol;
+ next = firstcol;
+ hidden = hiddenCols.getHiddenRegions();
+ lasthiddenregion = -1;
+
+ if (hidden != null)
+ {
+ int i = 0;
+ for (i = 0; i < hidden.size(); ++i)
+ {
+ if (current >= hidden.get(i)[0] && current <= hidden.get(i)[1])
+ {
+ // current is hidden, move to right
+ current = hidden.get(i)[1] + 1;
+ next = current;
+ }
+ if (current < hidden.get(i)[0])
+ {
+ break;
+ }
+ }
+ lasthiddenregion = i - 1;
+
+ for (i = hidden.size() - 1; i >= 0; --i)
+ {
+ if (last >= hidden.get(i)[0] && last <= hidden.get(i)[1])
+ {
+ // last is hidden, move to left
+ last = hidden.get(i)[0] - 1;
+ }
+ if (last > hidden.get(i)[1])
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return next <= last;
+ }
+
+ @Override
+ public Integer next()
+ {
+ if (next > last)
+ {
+ throw new NoSuchElementException();
+ }
+ current = next;
+ if ((hidden != null) && (lasthiddenregion + 1 < hidden.size()))
+ {
+ // still some more hidden regions
+ if (next + 1 < hidden.get(lasthiddenregion + 1)[0])
+ {
+ // next+1 is still before the next hidden region
+ next++;
+ }
+ else if ((next + 1 >= hidden.get(lasthiddenregion + 1)[0])
+ && (next + 1 <= hidden.get(lasthiddenregion + 1)[1]))
+ {
+ // next + 1 is in the next hidden region
+ next = hidden.get(lasthiddenregion + 1)[1] + 1;
+ lasthiddenregion++;
+ }
+ }
+ else
+ {
+ // finished with hidden regions, just increment normally
+ next++;
+ }
+ return current;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
+
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import jalview.api.AlignmentRowsCollectionI;
+
+import java.util.Iterator;
+
+public class VisibleRowsCollection implements AlignmentRowsCollectionI
+{
+ int start;
+
+ int end;
+
+ AlignmentI alignment;
+
+ public VisibleRowsCollection(int s, int e, AlignmentI al)
+ {
+ start = s;
+ end = e;
+ alignment = al;
+ }
+
+ @Override
+ public Iterator<Integer> iterator()
+ {
+ return new VisibleRowsIterator(start, end, alignment);
+ }
+
+ @Override
+ public boolean isHidden(int seq)
+ {
+ return false;
+ }
+
+ @Override
+ public SequenceI getSequence(int seq)
+ {
+ return alignment.getSequenceAtAbsoluteIndex(seq);
+ }
+}
+
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An iterator which iterates over all visible rows in an alignment
+ *
+ * @author kmourao
+ *
+ */
+public class VisibleRowsIterator implements Iterator<Integer>
+{
+ private int last;
+
+ private int current;
+
+ private int next;
+
+ private HiddenSequences hidden;
+
+ private AlignmentI al;
+
+ /**
+ * Create an iterator for all visible rows in the alignment
+ *
+ * @param firstrow
+ * absolute row index to start from
+ * @param lastrow
+ * absolute row index to end at
+ * @param alignment
+ * alignment to work with
+ */
+ public VisibleRowsIterator(int firstrow, int lastrow, AlignmentI alignment)
+ {
+ al = alignment;
+ current = firstrow;
+ last = lastrow;
+ hidden = al.getHiddenSequences();
+ while (last > current && hidden.isHidden(last))
+ {
+ last--;
+ }
+ current = firstrow;
+ while (current < last && hidden.isHidden(current))
+ {
+ current++;
+ }
+ next = current;
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return next <= last;
+ }
+
+ @Override
+ public Integer next()
+ {
+ if (next > last)
+ {
+ throw new NoSuchElementException();
+ }
+ current = next;
+ do
+ {
+ next++;
+ } while (next <= last && hidden.isHidden(next));
+ return current;
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
+
/*
* update these constants when Jalview has been checked / updated for
- * changes to Ensembl REST API
+ * changes to Ensembl REST API (ref JAL-2105)
* @see https://github.com/Ensembl/ensembl-rest/wiki/Change-log
* @see http://rest.ensembl.org/info/rest?content-type=application/json
*/
- private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "4.8";
+ private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "5.0";
- private static final String LATEST_ENSEMBL_REST_VERSION = "4.8";
+ private static final String LATEST_ENSEMBL_REST_VERSION = "5.0";
private static final String REST_CHANGE_LOG = "https://github.com/Ensembl/ensembl-rest/wiki/Change-log";
boolean laterVersion = StringUtils.compareVersions(version, expected) == 1;
if (laterVersion)
{
- System.err.println(String.format(
- "Expected %s REST version %s but found %s, see %s",
- getDbSource(), expected, version, REST_CHANGE_LOG));
+ System.err
+ .println(String
+ .format("EnsemblRestClient expected %s REST version %s but found %s, see %s",
+ getDbSource(), expected, version,
+ REST_CHANGE_LOG));
}
info.restVersion = version;
} catch (Throwable t)
import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.io.DataSourceType;
* TODO
*/
public void superposeStructures(AlignmentI alignment, int refStructure,
- ColumnSelection hiddenCols)
+ HiddenColumns hiddenCols)
{
superposeStructures(new AlignmentI[] { alignment },
new int[] { refStructure },
- new ColumnSelection[] { hiddenCols });
+ new HiddenColumns[] { hiddenCols });
}
/**
*/
@Override
public String superposeStructures(AlignmentI[] _alignment,
- int[] _refStructure, ColumnSelection[] _hiddenCols)
+ int[] _refStructure, HiddenColumns[] _hiddenCols)
{
while (viewer.isScriptExecuting())
{
{
int refStructure = _refStructure[a];
AlignmentI alignment = _alignment[a];
- ColumnSelection hiddenCols = _hiddenCols[a];
+ HiddenColumns hiddenCols = _hiddenCols[a];
if (a > 0
&& selectioncom.length() > 0
&& !selectioncom.substring(selectioncom.length() - 1).equals(
import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceI;
import jalview.renderer.seqfeatures.FeatureColourFinder;
import jalview.structure.StructureMapping;
FeatureRenderer fr = viewPanel.getFeatureRenderer();
FeatureColourFinder finder = new FeatureColourFinder(fr);
AlignViewportI viewport = viewPanel.getAlignViewport();
- ColumnSelection cs = viewport.getColumnSelection();
+ HiddenColumns cs = viewport.getAlignment().getHiddenColumns();
AlignmentI al = viewport.getAlignment();
List<StructureMappingcommandSet> cset = new ArrayList<StructureMappingcommandSet>();
import jalview.api.FeatureRenderer;
import jalview.api.SequenceRenderer;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.renderer.seqfeatures.FeatureColourFinder;
FeatureRenderer fr = viewPanel.getFeatureRenderer();
FeatureColourFinder finder = new FeatureColourFinder(fr);
AlignViewportI viewport = viewPanel.getAlignViewport();
- ColumnSelection cs = viewport.getColumnSelection();
+ HiddenColumns cs = viewport.getAlignment().getHiddenColumns();
AlignmentI al = viewport.getAlignment();
Map<Object, AtomSpecModel> colourMap = new LinkedHashMap<Object, AtomSpecModel>();
Color lastColour = null;
import jalview.api.structures.JalviewStructureDisplayI;
import jalview.bin.Cache;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResultsI;
if (getSsm() != null)
{
getSsm().addStructureViewerListener(this);
- // ssm.addSelectionListener(this);
- refreshGUI();
}
return true;
} catch (Exception q)
*/
@Override
public String superposeStructures(AlignmentI[] _alignment,
- int[] _refStructure, ColumnSelection[] _hiddenCols)
+ int[] _refStructure, HiddenColumns[] _hiddenCols)
{
StringBuilder allComs = new StringBuilder(128);
String[] files = getPdbFile();
{
int refStructure = _refStructure[a];
AlignmentI alignment = _alignment[a];
- ColumnSelection hiddenCols = _hiddenCols[a];
+ HiddenColumns hiddenCols = _hiddenCols[a];
if (refStructure >= files.length)
{
protected HashSet<String> paginatorCart = new HashSet<String>();
+ private static final int MIN_WIDTH = 670;
+
+ private static final int MIN_HEIGHT = 300;
+
protected static final DecimalFormat totalNumberformatter = new DecimalFormat(
"###,###");
try
{
jbInit();
+ mainFrame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
mainFrame.addFocusListener(new FocusAdapter()
{
@Override
if (foundDataRow != null && foundDataRow.length > 0)
{
result = new ArrayList<FTSData>();
- String titleRow = getDataColumnsFieldsAsTabDelimitedString(uniprotRestRequest
- .getWantedFields());
- // System.out.println(">>>>Title row : " + titleRow);
+ boolean firstRow = true;
for (String dataRow : foundDataRow)
{
- if (dataRow.equalsIgnoreCase(titleRow))
+ // The first data row is usually the header data. This should be
+ // filtered out from the rest of the data See: JAL-2485
+ if (firstRow)
{
- // System.out.println(">>>>>>>>>> matched!!!");
+ firstRow = false;
continue;
}
// System.out.println(dataRow);
import jalview.api.FeatureSettingsControllerI;
import jalview.api.SplitContainerI;
import jalview.api.ViewStyleI;
-import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
import jalview.bin.Cache;
import jalview.bin.Jalview;
import jalview.commands.CommandI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.AlignmentView;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.HiddenSequences;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SeqCigar;
import jalview.io.FileFormatI;
import jalview.io.FileFormats;
import jalview.io.FileLoader;
+import jalview.io.FileParse;
import jalview.io.FormatAdapter;
import jalview.io.HtmlSvgOutput;
import jalview.io.IdentifyFile;
import jalview.io.JalviewFileView;
import jalview.io.JnetAnnotationMaker;
import jalview.io.NewickFile;
+import jalview.io.ScoreMatrixFile;
import jalview.io.TCoffeeScoreFile;
import jalview.jbgui.GAlignFrame;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.ColourSchemes;
import jalview.schemes.ResidueColourScheme;
-import jalview.schemes.ResidueProperties;
import jalview.schemes.TCoffeeColourScheme;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
* @param height
* height of frame.
*/
- public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,
+ public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns,
int width, int height)
{
this(al, hiddenColumns, width, height, null);
* @param sequenceSetId
* (may be null)
*/
- public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,
+ public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns,
int width, int height, String sequenceSetId)
{
this(al, hiddenColumns, width, height, sequenceSetId, null);
* @param viewId
* (may be null)
*/
- public AlignFrame(AlignmentI al, ColumnSelection hiddenColumns,
+ public AlignFrame(AlignmentI al, HiddenColumns hiddenColumns,
int width, int height, String sequenceSetId, String viewId)
{
setSize(width, height);
}
public AlignFrame(AlignmentI al, SequenceI[] hiddenSeqs,
- ColumnSelection hiddenColumns, int width, int height)
+ HiddenColumns hiddenColumns, int width, int height)
{
setSize(width, height);
setMenusFromViewport(viewport);
buildSortByAnnotationScoresMenu();
- buildTreeMenu();
+ calculateTree.addActionListener(new ActionListener()
+ {
+
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ openTreePcaDialog();
+ }
+ });
buildColourMenu();
if (Desktop.desktop != null)
exportData.getAlignment(), // class cast exceptions will
// occur in the distant future
exportData.getOmitHidden(), exportData.getStartEndPostions(),
- f.getCacheSuffixDefault(format),
- viewport.getColumnSelection());
+ f.getCacheSuffixDefault(format), viewport.getAlignment()
+ .getHiddenColumns());
if (output == null)
{
cap.setText(new FormatAdapter(alignPanel, exportData.getSettings())
.formatSequences(format, exportData.getAlignment(),
exportData.getOmitHidden(),
- exportData.getStartEndPostions(),
- viewport.getColumnSelection()));
+ exportData
+ .getStartEndPostions(), viewport
+ .getAlignment().getHiddenColumns()));
Desktop.addInternalFrame(cap, MessageManager.formatMessage(
"label.alignment_output_command",
new Object[] { e.getActionCommand() }), 600, 500);
alignmentToExport = viewport.getAlignment();
}
alignmentStartEnd = alignmentToExport
- .getVisibleStartAndEndIndex(viewport.getColumnSelection()
- .getHiddenColumns());
+ .getVisibleStartAndEndIndex(viewport.getAlignment()
+ .getHiddenColumns()
+ .getHiddenRegions());
AlignmentExportData ed = new AlignmentExportData(alignmentToExport,
omitHidden, alignmentStartEnd, settings);
return ed;
hiddenColumns = new ArrayList<int[]>();
int hiddenOffset = viewport.getSelectionGroup().getStartRes(), hiddenCutoff = viewport
.getSelectionGroup().getEndRes();
- for (int[] region : viewport.getColumnSelection().getHiddenColumns())
+ for (int[] region : viewport.getAlignment().getHiddenColumns()
+ .getHiddenRegions())
{
if (region[0] >= hiddenOffset && region[1] <= hiddenCutoff)
{
*/
if (ResidueColourScheme.USER_DEFINED.equals(name))
{
- new UserDefinedColours(alignPanel, null);
+ new UserDefinedColours(alignPanel);
return;
}
public void changeColour(ColourSchemeI cs)
{
// TODO: pull up to controller method
- if (cs != null)
- {
- ColourMenuHelper.setColourSelected(colourMenu, cs.getSchemeName());
- }
+ ColourMenuHelper.setColourSelected(colourMenu, cs);
viewport.setGlobalColourScheme(cs);
{
SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
AlignmentSorter.sortByPID(viewport.getAlignment(), viewport
- .getAlignment().getSequenceAt(0), null);
+ .getAlignment().getSequenceAt(0));
addHistoryItem(new OrderCommand("Pairwise Sort", oldOrder,
viewport.getAlignment()));
alignPanel.paintAlignment(true);
}
}
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- @Override
- public void PCAMenuItem_actionPerformed(ActionEvent e)
- {
- if (((viewport.getSelectionGroup() != null)
- && (viewport.getSelectionGroup().getSize() < 4) && (viewport
- .getSelectionGroup().getSize() > 0))
- || (viewport.getAlignment().getHeight() < 4))
- {
- JvOptionPane
- .showInternalMessageDialog(
- this,
- MessageManager
- .getString("label.principal_component_analysis_must_take_least_four_input_sequences"),
- MessageManager
- .getString("label.sequence_selection_insufficient"),
- JvOptionPane.WARNING_MESSAGE);
-
- return;
- }
-
- new PCAPanel(alignPanel);
- }
-
@Override
public void autoCalculate_actionPerformed(ActionEvent e)
{
}
/**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- @Override
- public void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
- {
- newTreePanel("AV", "PID", "Average distance tree using PID");
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- @Override
- public void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
- {
- newTreePanel("NJ", "PID", "Neighbour joining tree using PID");
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- @Override
- protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
- {
- newTreePanel("NJ", "BL", "Neighbour joining tree using BLOSUM62");
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- @Override
- protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
- {
- newTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
- }
-
- /**
- * DOCUMENT ME!
+ * Constructs a tree panel and adds it to the desktop
*
* @param type
- * DOCUMENT ME!
- * @param pwType
- * DOCUMENT ME!
- * @param title
- * DOCUMENT ME!
+ * tree type (NJ or AV)
+ * @param modelName
+ * name of score model used to compute the tree
+ * @param options
+ * parameters for the distance or similarity calculation
*/
- void newTreePanel(String type, String pwType, String title)
+ void newTreePanel(String type, String modelName, SimilarityParamsI options)
{
+ String frameTitle = "";
TreePanel tp;
+ boolean onSelection = false;
if (viewport.getSelectionGroup() != null
&& viewport.getSelectionGroup().getSize() > 0)
{
- if (viewport.getSelectionGroup().getSize() < 3)
- {
- JvOptionPane
- .showMessageDialog(
- Desktop.desktop,
- MessageManager
- .getString("label.you_need_more_two_sequences_selected_build_tree"),
- MessageManager
- .getString("label.not_enough_sequences"),
- JvOptionPane.WARNING_MESSAGE);
- return;
- }
-
SequenceGroup sg = viewport.getSelectionGroup();
/* Decide if the selection is a column region */
return;
}
}
-
- title = title + " on region";
- tp = new TreePanel(alignPanel, type, pwType);
+ onSelection = true;
}
else
{
- // are the visible sequences aligned?
- if (!viewport.getAlignment().isAligned(false))
- {
- JvOptionPane
- .showMessageDialog(
- Desktop.desktop,
- MessageManager
- .getString("label.sequences_must_be_aligned_before_creating_tree"),
- MessageManager
- .getString("label.sequences_not_aligned"),
- JvOptionPane.WARNING_MESSAGE);
-
- return;
- }
-
if (viewport.getAlignment().getHeight() < 2)
{
return;
}
-
- tp = new TreePanel(alignPanel, type, pwType);
}
- title += " from ";
+ tp = new TreePanel(alignPanel, type, modelName, options);
+ frameTitle = tp.getPanelTitle() + (onSelection ? " on region" : "");
+
+ frameTitle += " from ";
if (viewport.viewName != null)
{
- title += viewport.viewName + " of ";
+ frameTitle += viewport.viewName + " of ";
}
- title += this.title;
+ frameTitle += this.title;
- Desktop.addInternalFrame(tp, title, 600, 500);
+ Desktop.addInternalFrame(tp, frameTitle, 600, 500);
}
/**
* call. Listeners are added to remove the menu item when the treePanel is
* closed, and adjust the tree leaf to sequence mapping when the alignment is
* modified.
- *
- * @param treePanel
- * Displayed tree window.
- * @param title
- * SortBy menu item title.
*/
@Override
- public void buildTreeMenu()
+ public void buildTreeSortMenu()
{
- calculateTree.removeAll();
- // build the calculate menu
-
- for (final String type : new String[] { "NJ", "AV" })
- {
- String treecalcnm = MessageManager.getString("label.tree_calc_"
- + type.toLowerCase());
- for (final String pwtype : ResidueProperties.scoreMatrices.keySet())
- {
- JMenuItem tm = new JMenuItem();
- ScoreModelI sm = ResidueProperties.scoreMatrices.get(pwtype);
- if (sm.isDNA() == viewport.getAlignment().isNucleotide()
- || sm.isProtein() == !viewport.getAlignment()
- .isNucleotide())
- {
- String smn = MessageManager.getStringOrReturn(
- "label.score_model_", sm.getName());
- final String title = MessageManager.formatMessage(
- "label.treecalc_title", treecalcnm, smn);
- tm.setText(title);//
- tm.addActionListener(new java.awt.event.ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- newTreePanel(type, pwtype, title);
- }
- });
- calculateTree.add(tm);
- }
-
- }
- }
sortByTreeMenu.removeAll();
List<Component> comps = PaintRefresher.components.get(viewport
if (value == JalviewFileChooser.APPROVE_OPTION)
{
- String choice = chooser.getSelectedFile().getPath();
- jalview.bin.Cache.setProperty("LAST_DIRECTORY", choice);
- jalview.io.NewickFile fin = null;
+ String filePath = chooser.getSelectedFile().getPath();
+ Cache.setProperty("LAST_DIRECTORY", filePath);
+ NewickFile fin = null;
try
{
- fin = new NewickFile(choice, DataSourceType.FILE);
- viewport.setCurrentTree(ShowNewickTree(fin, choice).getTree());
+ fin = new NewickFile(filePath, DataSourceType.FILE);
+ viewport.setCurrentTree(showNewickTree(fin, filePath).getTree());
} catch (Exception ex)
{
JvOptionPane
}
}
- public TreePanel ShowNewickTree(NewickFile nf, String title)
+ public TreePanel showNewickTree(NewickFile nf, String treeTitle)
{
- return ShowNewickTree(nf, title, 600, 500, 4, 5);
+ return showNewickTree(nf, treeTitle, 600, 500, 4, 5);
}
- public TreePanel ShowNewickTree(NewickFile nf, String title,
- AlignmentView input)
- {
- return ShowNewickTree(nf, title, input, 600, 500, 4, 5);
- }
-
- public TreePanel ShowNewickTree(NewickFile nf, String title, int w,
+ public TreePanel showNewickTree(NewickFile nf, String treeTitle, int w,
int h, int x, int y)
{
- return ShowNewickTree(nf, title, null, w, h, x, y);
+ return showNewickTree(nf, treeTitle, null, w, h, x, y);
}
/**
- * Add a treeviewer for the tree extracted from a newick file object to the
+ * Add a treeviewer for the tree extracted from a Newick file object to the
* current alignment view
*
* @param nf
* position
* @return TreePanel handle
*/
- public TreePanel ShowNewickTree(NewickFile nf, String title,
+ public TreePanel showNewickTree(NewickFile nf, String treeTitle,
AlignmentView input, int w, int h, int x, int y)
{
TreePanel tp = null;
if (nf.getTree() != null)
{
- tp = new TreePanel(alignPanel, "FromFile", title, nf, input);
+ tp = new TreePanel(alignPanel, nf, treeTitle, input);
tp.setSize(w, h);
tp.setLocation(x, y);
}
- Desktop.addInternalFrame(tp, title, w, h);
+ Desktop.addInternalFrame(tp, treeTitle, w, h);
}
} catch (Exception ex)
{
}
/**
- * Attempt to load a "dropped" file or URL string: First by testing whether
- * it's an Annotation file, then a JNet file, and finally a features file. If
- * all are false then the user may have dropped an alignment file onto this
- * AlignFrame.
+ * Attempt to load a "dropped" file or URL string, by testing in turn for
+ * <ul>
+ * <li>an Annotation file</li>
+ * <li>a JNet file</li>
+ * <li>a features file</li>
+ * <li>else try to interpret as an alignment file</li>
+ * </ul>
*
* @param file
* either a filename or a URL string.
{
format = new IdentifyFile().identify(file, sourceType);
}
- if (FileFormat.Jnet.equals(format))
+ if (FileFormat.ScoreMatrix == format)
+ {
+ ScoreMatrixFile sm = new ScoreMatrixFile(new FileParse(file,
+ sourceType));
+ sm.parse();
+ // todo: i18n this message
+ statusBar
+ .setText(MessageManager.formatMessage(
+ "label.successfully_loaded_matrix",
+ sm.getMatrixName()));
+ }
+ else if (FileFormat.Jnet.equals(format))
{
JPredFile predictions = new JPredFile(file, sourceType);
new JnetAnnotationMaker();
viewport.getAlignment(), 0, false);
SequenceI repseq = viewport.getAlignment().getSequenceAt(0);
viewport.getAlignment().setSeqrep(repseq);
- ColumnSelection cs = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
cs.hideInsertionsFor(repseq);
- viewport.setColumnSelection(cs);
+ viewport.getAlignment().setHiddenColumns(cs);
isAnnotation = true;
}
// else if (IdentifyFile.FeaturesFile.equals(format))
colourMenu.add(annotationColour);
ColourSchemeI colourScheme = viewport.getGlobalColourScheme();
- String schemeName = colourScheme == null ? null : colourScheme
- .getSchemeName();
+ ColourMenuHelper.setColourSelected(colourMenu, colourScheme);
+ }
- ColourMenuHelper.setColourSelected(colourMenu, schemeName);
+ /**
+ * Open a dialog (if not already open) that allows the user to select and
+ * calculate PCA or Tree analysis
+ */
+ protected void openTreePcaDialog()
+ {
+ if (alignPanel.getCalculationDialog() == null)
+ {
+ new CalculationChooser(AlignFrame.this);
+ }
}
}
import jalview.analysis.AlignmentUtils;
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
-import jalview.analysis.NJTree;
+import jalview.analysis.TreeModel;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.api.FeatureColourI;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
import jalview.structure.VamsasSource;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
-import jalview.viewmodel.ViewportRanges;
import jalview.ws.params.AutoCalcSetting;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
+import java.awt.FontMetrics;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Hashtable;
{
Font font;
- NJTree currentTree = null;
+ TreeModel currentTree = null;
boolean cursorMode = false;
*/
public AlignViewport(AlignmentI al)
{
- setAlignment(al);
+ super(al);
init();
}
public AlignViewport(AlignmentI al, String seqsetid, String viewid)
{
+ super(al);
sequenceSetID = seqsetid;
viewId = viewid;
// TODO remove these once 2.4.VAMSAS release finished
{
Cache.log.debug("Setting viewport's view id : " + viewId);
}
- setAlignment(al);
init();
+
}
/**
* @param hiddenColumns
* ColumnSelection
*/
- public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns)
+ public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns)
{
- setAlignment(al);
+ super(al);
if (hiddenColumns != null)
{
- colSel = hiddenColumns;
+ al.setHiddenColumns(hiddenColumns);
}
init();
}
* @param seqsetid
* (may be null)
*/
- public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns,
+ public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns,
String seqsetid)
{
this(al, hiddenColumns, seqsetid, null);
* @param viewid
* (may be null)
*/
- public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns,
+ public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns,
String seqsetid, String viewid)
{
+ super(al);
sequenceSetID = seqsetid;
viewId = viewid;
// TODO remove these once 2.4.VAMSAS release finished
{
Cache.log.debug("Setting viewport's view id : " + viewId);
}
- setAlignment(al);
+
if (hiddenColumns != null)
{
- colSel = hiddenColumns;
+ al.setHiddenColumns(hiddenColumns);
}
init();
}
void init()
{
- ranges = new ViewportRanges(this.alignment);
applyViewProperties();
String fontName = Cache.getDefault("FONT_NAME", "SansSerif");
false);
showGroupConsensus = Cache.getDefault("SHOW_GROUP_CONSENSUS", false);
showConsensus = Cache.getDefault("SHOW_IDENTITY", true);
+
+ showOccupancy = Cache.getDefault(Preferences.SHOW_OCCUPANCY, true);
}
initAutoAnnotation();
String colourProperty = alignment.isNucleotide() ? Preferences.DEFAULT_COLOUR_NUC
boolean validCharWidth;
/**
- * update view settings with the given font. You may need to call
- * alignPanel.fontChanged to update the layout geometry
- *
- * @param setGrid
- * when true, charWidth/height is set according to font mentrics
+ * {@inheritDoc}
*/
+ @Override
public void setFont(Font f, boolean setGrid)
{
font = f;
Container c = new Container();
- java.awt.FontMetrics fm = c.getFontMetrics(font);
- int w = viewStyle.getCharWidth(), ww = fm.charWidth('M'), h = viewStyle
- .getCharHeight();
if (setGrid)
{
+ FontMetrics fm = c.getFontMetrics(font);
+ int ww = fm.charWidth('M');
setCharHeight(fm.getHeight());
setCharWidth(ww);
}
* @param tree
* DOCUMENT ME!
*/
- public void setCurrentTree(NJTree tree)
+ public void setCurrentTree(TreeModel tree)
{
currentTree = tree;
}
*
* @return DOCUMENT ME!
*/
- public NJTree getCurrentTree()
+ public TreeModel getCurrentTree()
{
return currentTree;
}
{
end = alignment.getWidth();
}
- viscontigs = colSel.getVisibleContigs(start, end);
+ viscontigs = alignment.getHiddenColumns().getVisibleContigs(start, end);
return viscontigs;
}
jalview.structure.StructureSelectionManager
.getStructureSelectionManager(Desktop.instance).sendSelection(
new SequenceGroup(getSelectionGroup()),
- new ColumnSelection(getColumnSelection()), this);
+ new ColumnSelection(getColumnSelection()),
+ new HiddenColumns(getAlignment().getHiddenColumns()),
+ this);
}
/**
import jalview.api.AlignmentViewPanel;
import jalview.bin.Cache;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceGroup;
private PropertyChangeListener propertyChangeListener;
+ private CalculationChooser calculationDialog;
+
/**
* Creates a new AlignmentPanel object.
*
{
av.alignmentChanged(this);
+ if (getCalculationDialog() != null)
+ {
+ getCalculationDialog().validateCalcTypes();
+ }
+
alignFrame.updateEditMenuBar();
paintAlignment(true);
}
if (av.hasHiddenColumns())
{
- start = av.getColumnSelection().findColumnPosition(start);
- end = av.getColumnSelection().findColumnPosition(end);
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ start = hidden.findColumnPosition(start);
+ end = hidden.findColumnPosition(end);
if (start == end)
{
- if (!av.getColumnSelection().isVisible(r[0]))
+ if (!hidden.isVisible(r[0]))
{
// don't scroll - position isn't visible
return false;
if (av.hasHiddenColumns())
{
// reset the width to exclude hidden columns
- width = av.getColumnSelection().findColumnPosition(width);
+ width = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(width);
}
hextent = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
int canvasWidth = getSeqPanel().seqCanvas
int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
int resWidth = getSeqPanel().seqCanvas.getWrappedCanvasWidth(pwidth
int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth);
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth);
}
int height = ((av.getAlignment().getHeight() + 1) * av.getCharHeight())
int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
int height = ((maxwidth / chunkWidth) + 1) * cHeight;
PaintRefresher.RemoveComponent(getIdPanel().getIdCanvas());
PaintRefresher.RemoveComponent(this);
+ closeChildFrames();
+
/*
* try to ensure references are nulled
*/
}
/**
+ * Close any open dialogs that would be orphaned when this one is closed
+ */
+ protected void closeChildFrames()
+ {
+ if (calculationDialog != null)
+ {
+ calculationDialog.closeFrame();
+ }
+ }
+
+ /**
* hides or shows dynamic annotation rows based on groups and av state flags
*/
public void updateAnnotation()
repaint();
}
}
+
+ /**
+ * Set the reference to the PCA/Tree chooser dialog for this panel. This
+ * reference should be nulled when the dialog is closed.
+ *
+ * @param calculationChooser
+ */
+ public void setCalculationDialog(CalculationChooser calculationChooser)
+ {
+ calculationDialog = calculationChooser;
+ }
+
+ /**
+ * Returns the reference to the PCA/Tree chooser dialog for this panel (null
+ * if none is open)
+ */
+ public CalculationChooser getCalculationDialog()
+ {
+ return calculationDialog;
+ }
}
private JCheckBox thresholdIsMin = new JCheckBox();
+ protected static final int MIN_WIDTH = 500;
+
+ protected static final int MIN_HEIGHT = 240;
+
public AnnotationColourChooser(AlignViewport av, final AlignmentPanel ap)
{
super(av, ap);
Desktop.addInternalFrame(frame,
MessageManager.getString("label.colour_by_annotation"), 520,
215);
-
+ frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
addSliderChangeListener();
addSliderMouseListeners();
package jalview.gui;
-import jalview.datamodel.AlignmentAnnotation;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.io.cache.JvCacheableInputBox;
import jalview.schemes.AnnotationColourGradient;
import jalview.util.MessageManager;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
+import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
private int actionOption = ACTION_OPTION_SELECT;
- private ColumnSelection oldColumnSelection;
+ private HiddenColumns oldHiddenColumns;
+
+ protected int MIN_WIDTH = 420;
+
+ protected int MIN_HEIGHT = 430;
public AnnotationColumnChooser(AlignViewport av, final AlignmentPanel ap)
{
Desktop.addInternalFrame(frame,
MessageManager.getString("label.select_by_annotation"), 520,
215);
+ frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
addSliderChangeListener();
addSliderMouseListeners();
{
return;
}
- setOldColumnSelection(av.getColumnSelection());
+ setOldHiddenColumns(av.getAlignment().getHiddenColumns());
adjusting = true;
setAnnotations(new JComboBox<String>(getAnnotationItems(false)));
populateThresholdComboBox(threshold);
-
+ AnnotationColumnChooser lastChooser = av
+ .getAnnotationColumnSelectionState();
// restore Object state from the previous session if one exists
- if (av.getAnnotationColumnSelectionState() != null)
+ if (lastChooser != null)
{
- currentSearchPanel = av.getAnnotationColumnSelectionState()
+ currentSearchPanel = lastChooser
.getCurrentSearchPanel();
- currentStructureFilterPanel = av.getAnnotationColumnSelectionState()
+ currentStructureFilterPanel = lastChooser
.getCurrentStructureFilterPanel();
- annotations.setSelectedIndex(av.getAnnotationColumnSelectionState()
+ annotations.setSelectedIndex(lastChooser
.getAnnotations().getSelectedIndex());
- threshold.setSelectedIndex(av.getAnnotationColumnSelectionState()
+ threshold.setSelectedIndex(lastChooser
.getThreshold().getSelectedIndex());
- actionOption = av.getAnnotationColumnSelectionState()
+ actionOption = lastChooser
.getActionOption();
+ percentThreshold.setSelected(lastChooser.percentThreshold
+ .isSelected());
}
try
thresholdPanel.setFont(JvSwingUtils.getLabelFont());
thresholdPanel.setLayout(new MigLayout("", "[left][right]", "[][]"));
+ percentThreshold.setBackground(Color.white);
+ percentThreshold.setFont(JvSwingUtils.getLabelFont());
+
JPanel actionPanel = new JPanel();
actionPanel.setBackground(Color.white);
actionPanel.setFont(JvSwingUtils.getLabelFont());
ngStructureFilterPanel = new StructureFilterPanel(this);
thresholdPanel.add(getThreshold());
- thresholdPanel.add(thresholdValue, "wrap");
- thresholdPanel.add(slider, "grow, span, wrap");
+ thresholdPanel.add(percentThreshold, "wrap");
+ thresholdPanel.add(slider, "grow");
+ thresholdPanel.add(thresholdValue, "span, wrap");
actionPanel.add(ok);
actionPanel.add(cancel);
@Override
protected void reset()
{
- if (this.getOldColumnSelection() != null)
+ if (this.getOldHiddenColumns() != null)
{
av.getColumnSelection().clear();
if (av.getAnnotationColumnSelectionState() != null)
{
- ColumnSelection oldSelection = av
+ HiddenColumns oldHidden = av
.getAnnotationColumnSelectionState()
- .getOldColumnSelection();
- if (oldSelection != null && oldSelection.getHiddenColumns() != null
- && !oldSelection.getHiddenColumns().isEmpty())
+ .getOldHiddenColumns();
+ if (oldHidden != null && oldHidden.getHiddenRegions() != null
+ && !oldHidden.getHiddenRegions().isEmpty())
{
- for (Iterator<int[]> itr = oldSelection.getHiddenColumns()
+ for (Iterator<int[]> itr = oldHidden.getHiddenRegions()
.iterator(); itr.hasNext();)
{
int positions[] = itr.next();
av.hideColumns(positions[0], positions[1]);
}
}
- av.setColumnSelection(oldSelection);
+ av.getAlignment().setHiddenColumns(oldHidden);
}
ap.paintAlignment(true);
}
slider.setEnabled(true);
thresholdValue.setEnabled(true);
+ percentThreshold.setEnabled(true);
if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD)
{
slider.setEnabled(false);
thresholdValue.setEnabled(false);
thresholdValue.setText("");
+ percentThreshold.setEnabled(false);
// build filter params
}
else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD)
slider.setMinimum((int) (getCurrentAnnotation().graphMin * 1000));
slider.setMaximum((int) (getCurrentAnnotation().graphMax * 1000));
slider.setValue((int) (getCurrentAnnotation().threshold.value * 1000));
- thresholdValue.setText(getCurrentAnnotation().threshold.value + "");
+
+ setThresholdValueText();
+
slider.setMajorTickSpacing((int) (range / 10f));
slider.setEnabled(true);
thresholdValue.setEnabled(true);
// build filter params
filterParams
.setThresholdType(AnnotationFilterParameter.ThresholdType.NO_THRESHOLD);
- if (getCurrentAnnotation().graph != AlignmentAnnotation.NO_GRAPH)
+ if (getCurrentAnnotation().isQuantitative())
{
filterParams
.setThresholdValue(getCurrentAnnotation().threshold.value);
ap.paintAlignment(true);
}
- public ColumnSelection getOldColumnSelection()
+ public HiddenColumns getOldHiddenColumns()
{
- return oldColumnSelection;
+ return oldHiddenColumns;
}
- public void setOldColumnSelection(ColumnSelection currentColumnSelection)
+ public void setOldHiddenColumns(HiddenColumns currentHiddenColumns)
{
- if (currentColumnSelection != null)
+ if (currentHiddenColumns != null)
{
- this.oldColumnSelection = new ColumnSelection(currentColumnSelection);
+ this.oldHiddenColumns = new HiddenColumns(currentHiddenColumns);
}
}
public void selectedAnnotationChanged()
{
String currentView = AnnotationColumnChooser.NO_GRAPH_VIEW;
- if (av.getAlignment().getAlignmentAnnotation()[annmap[getAnnotations()
- .getSelectedIndex()]].graph != AlignmentAnnotation.NO_GRAPH)
+ if (av.getAlignment()
+ .getAlignmentAnnotation()[annmap[getAnnotations()
+ .getSelectedIndex()]].isQuantitative())
{
currentView = AnnotationColumnChooser.GRAPH_VIEW;
}
Alignment ds = new Alignment(dseqs);
if (av.hasHiddenColumns())
{
- omitHidden = av.getColumnSelection().getVisibleSequenceStrings(0,
+ omitHidden = av.getAlignment().getHiddenColumns()
+ .getVisibleSequenceStrings(0,
sq.getLength(), seqs);
}
int[] alignmentStartEnd = new int[] { 0, ds.getWidth() - 1 };
- List<int[]> hiddenCols = av.getColumnSelection().getHiddenColumns();
+ List<int[]> hiddenCols = av.getAlignment().getHiddenColumns()
+ .getHiddenRegions();
if (hiddenCols != null)
{
alignmentStartEnd = av.getAlignment().getVisibleStartAndEndIndex(
if (av.hasHiddenColumns())
{
hiddenColumns = new ArrayList<int[]>();
- for (int[] region : av.getColumnSelection().getHiddenColumns())
+ for (int[] region : av.getAlignment().getHiddenColumns()
+ .getHiddenRegions())
{
hiddenColumns.add(new int[] { region[0], region[1] });
}
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceI;
import jalview.renderer.AnnotationRenderer;
import jalview.renderer.AwtRenderPanelI;
{
for (int index : av.getColumnSelection().getSelected())
{
- if (av.getColumnSelection().isVisible(index))
+ if (av.getAlignment().getHiddenColumns().isVisible(index))
{
anot[index] = null;
}
for (int index : av.getColumnSelection().getSelected())
{
- if (!av.getColumnSelection().isVisible(index))
+ if (!av.getAlignment().getHiddenColumns().isVisible(index))
{
continue;
}
for (int index : av.getColumnSelection().getSelected())
{
- if (!av.getColumnSelection().isVisible(index))
+ if (!av.getAlignment().getHiddenColumns().isVisible(index))
{
continue;
}
}
for (int index : av.getColumnSelection().getSelected())
{
- if (!av.getColumnSelection().isVisible(index))
+ if (!av.getAlignment().getHiddenColumns().isVisible(index))
{
continue;
}
StringBuilder collatedInput = new StringBuilder(64);
String last = "";
ColumnSelection viscols = av.getColumnSelection();
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
/*
* the selection list (read-only view) is in selection order, not
for (int index : selected)
{
// always check for current display state - just in case
- if (!viscols.isVisible(index))
+ if (!hidden.isVisible(index))
{
continue;
}
if (av.hasHiddenColumns())
{
- column = av.getColumnSelection().adjustForHiddenColumns(column);
+ column = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(column);
}
AlignmentAnnotation ann = aa[row];
protected JCheckBox seqAssociated = new JCheckBox();
+ protected JCheckBox percentThreshold = new JCheckBox();
+
protected JSlider slider = new JSlider();
protected JTextField thresholdValue = new JTextField(20);
{
if (!adjusting)
{
- thresholdValue.setText((slider.getValue() / 1000f) + "");
+ setThresholdValueText();
valueChanged(!sliderDragging);
}
}
});
}
+ /**
+ * update the text field from the threshold slider. preserves state of
+ * 'adjusting' so safe to call in init.
+ */
+ protected void setThresholdValueText()
+ {
+ boolean oldadj = adjusting;
+ adjusting = true;
+ if (percentThreshold.isSelected())
+ {
+ thresholdValue.setText("" + (slider.getValue() - slider.getMinimum())
+ * 100f / (slider.getMaximum() - slider.getMinimum()));
+ }
+ else
+ {
+ thresholdValue.setText((slider.getValue() / 1000f) + "");
+ }
+ adjusting = oldadj;
+ }
protected void addSliderMouseListeners()
{
try
{
float f = Float.parseFloat(thresholdValue.getText());
- slider.setValue((int) (f * 1000));
+ if (percentThreshold.isSelected())
+ {
+ slider.setValue(slider.getMinimum()
+ + ((int) ((f / 100f) * (slider.getMaximum() - slider
+ .getMinimum()))));
+ }
+ else
+ {
+ slider.setValue((int) (f * 1000));
+ }
updateView();
} catch (NumberFormatException ex)
{
}
}
+ protected void percentageValue_actionPerformed()
+ {
+ setThresholdValueText();
+ }
+
protected void thresholdIsMin_actionPerformed()
{
updateView();
}
});
+ percentThreshold.setText(MessageManager.getString("label.as_percentage"));
+ percentThreshold.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ if (!adjusting)
+ {
+ percentageValue_actionPerformed();
+ }
+ }
+ });
slider.setPaintLabels(false);
slider.setPaintTicks(true);
slider.setBackground(Color.white);
import jalview.analysis.AlignSeq;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.RnaViewerModel;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
@Override
public void selection(SequenceGroup seqsel, ColumnSelection colsel,
- SelectionSource source)
+ HiddenColumns hidden, SelectionSource source)
{
if (source != ap.av)
{
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.gui;
+
+import jalview.analysis.TreeBuilder;
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.analysis.scoremodels.SimilarityParams;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.SequenceGroup;
+import jalview.util.MessageManager;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.beans.PropertyVetoException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
+import javax.swing.JLayeredPane;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
+
+/**
+ * A dialog where a user can choose and action Tree or PCA calculation options
+ */
+public class CalculationChooser extends JPanel
+{
+ /*
+ * flag for whether gap matches residue in the PID calculation for a Tree
+ * - true gives Jalview 2.10.1 behaviour
+ * - set to false (using Groovy) for a more correct tree
+ * (JAL-374)
+ */
+ private static boolean treeMatchGaps = true;
+
+ private static final Font VERDANA_11PT = new Font("Verdana", 0, 11);
+
+ private static final int MIN_TREE_SELECTION = 3;
+
+ private static final int MIN_PCA_SELECTION = 4;
+
+ AlignFrame af;
+
+ JRadioButton pca;
+
+ JRadioButton neighbourJoining;
+
+ JRadioButton averageDistance;
+
+ JComboBox<String> modelNames;
+
+ JButton calculate;
+
+ private JInternalFrame frame;
+
+ private JCheckBox includeGaps;
+
+ private JCheckBox matchGaps;
+
+ private JCheckBox includeGappedColumns;
+
+ private JCheckBox shorterSequence;
+
+ final ComboBoxTooltipRenderer renderer = new ComboBoxTooltipRenderer();
+
+ List<String> tips = new ArrayList<String>();
+
+ /**
+ * Constructor
+ *
+ * @param af
+ */
+ public CalculationChooser(AlignFrame alignFrame)
+ {
+ this.af = alignFrame;
+ init();
+ af.alignPanel.setCalculationDialog(this);
+ }
+
+ /**
+ * Lays out the panel and adds it to the desktop
+ */
+ void init()
+ {
+ setLayout(new BorderLayout());
+ frame = new JInternalFrame();
+ frame.setContentPane(this);
+ this.setBackground(Color.white);
+ frame.addFocusListener(new FocusListener()
+ {
+
+ @Override
+ public void focusLost(FocusEvent e)
+ {
+ }
+
+ @Override
+ public void focusGained(FocusEvent e)
+ {
+ validateCalcTypes();
+ }
+ });
+ /*
+ * Layout consists of 3 or 4 panels:
+ * - first with choice of PCA or tree method NJ or AV
+ * - second with choice of score model
+ * - third with score model parameter options [suppressed]
+ * - fourth with OK and Cancel
+ */
+ pca = new JRadioButton(
+ MessageManager.getString("label.principal_component_analysis"));
+ pca.setOpaque(false);
+ neighbourJoining = new JRadioButton(
+ MessageManager.getString("label.tree_calc_nj"));
+ neighbourJoining.setSelected(true);
+ averageDistance = new JRadioButton(
+ MessageManager.getString("label.tree_calc_av"));
+ neighbourJoining.setOpaque(false);
+
+ JPanel calcChoicePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ calcChoicePanel.setOpaque(false);
+
+ // first create the Tree calculation's border panel
+ JPanel treePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ treePanel.setOpaque(false);
+
+ treePanel.setBorder(BorderFactory.createTitledBorder(MessageManager
+ .getString("label.tree")));
+
+ // then copy the inset dimensions for the border-less PCA panel
+ JPanel pcaBorderless = new JPanel(new FlowLayout(FlowLayout.LEFT));
+ Insets b = treePanel.getBorder().getBorderInsets(treePanel);
+ pcaBorderless.setBorder(BorderFactory.createEmptyBorder(2, b.left, 2,
+ b.right));
+ pcaBorderless.setOpaque(false);
+
+ pcaBorderless.add(pca, FlowLayout.LEFT);
+ calcChoicePanel.add(pcaBorderless, FlowLayout.LEFT);
+
+ treePanel.add(neighbourJoining);
+ treePanel.add(averageDistance);
+
+ calcChoicePanel.add(treePanel);
+
+ ButtonGroup calcTypes = new ButtonGroup();
+ calcTypes.add(pca);
+ calcTypes.add(neighbourJoining);
+ calcTypes.add(averageDistance);
+
+ ActionListener calcChanged = new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ validateCalcTypes();
+ }
+ };
+ pca.addActionListener(calcChanged);
+ neighbourJoining.addActionListener(calcChanged);
+ averageDistance.addActionListener(calcChanged);
+
+ /*
+ * score models drop-down - with added tooltips!
+ */
+ modelNames = buildModelOptionsList();
+
+ JPanel scoreModelPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ scoreModelPanel.setOpaque(false);
+ scoreModelPanel.add(modelNames);
+
+ /*
+ * score model parameters
+ */
+ JPanel paramsPanel = new JPanel(new GridLayout(5, 1));
+ paramsPanel.setOpaque(false);
+ includeGaps = new JCheckBox("Include gaps");
+ matchGaps = new JCheckBox("Match gaps");
+ includeGappedColumns = new JCheckBox("Include gapped columns");
+ shorterSequence = new JCheckBox("Match on shorter sequence");
+ paramsPanel.add(new JLabel("Pairwise sequence scoring options"));
+ paramsPanel.add(includeGaps);
+ paramsPanel.add(matchGaps);
+ paramsPanel.add(includeGappedColumns);
+ paramsPanel.add(shorterSequence);
+
+ /*
+ * OK / Cancel buttons
+ */
+ calculate = new JButton(MessageManager.getString("action.calculate"));
+ calculate.setFont(VERDANA_11PT);
+ calculate.addActionListener(new java.awt.event.ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ calculate_actionPerformed();
+ }
+ });
+ JButton close = new JButton(MessageManager.getString("action.close"));
+ close.setFont(VERDANA_11PT);
+ close.addActionListener(new java.awt.event.ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ close_actionPerformed();
+ }
+ });
+ JPanel actionPanel = new JPanel();
+ actionPanel.setOpaque(false);
+ actionPanel.add(calculate);
+ actionPanel.add(close);
+
+ boolean includeParams = false;
+ this.add(calcChoicePanel, BorderLayout.CENTER);
+ calcChoicePanel.add(scoreModelPanel);
+ if (includeParams)
+ {
+ scoreModelPanel.add(paramsPanel);
+ }
+ this.add(actionPanel, BorderLayout.SOUTH);
+
+ int width = 350;
+ int height = includeParams ? 420 : 240;
+
+ setMinimumSize(new Dimension(325, height - 10));
+ String title = MessageManager.getString("label.choose_calculation");
+ if (af.getViewport().viewName != null)
+ {
+ title = title + " (" + af.getViewport().viewName + ")";
+ }
+
+ Desktop.addInternalFrame(frame, title, width, height, false);
+ calcChoicePanel.doLayout();
+ revalidate();
+ /*
+ * null the AlignmentPanel's reference to the dialog when it is closed
+ */
+ frame.addInternalFrameListener(new InternalFrameAdapter()
+ {
+ @Override
+ public void internalFrameClosed(InternalFrameEvent evt)
+ {
+ af.alignPanel.setCalculationDialog(null);
+ };
+ });
+
+ frame.setLayer(JLayeredPane.PALETTE_LAYER);
+ }
+
+ /**
+ * enable calculations applicable for the current alignment or selection.
+ */
+ protected void validateCalcTypes()
+ {
+ int size = af.getViewport().getAlignment().getHeight();
+ if (af.getViewport().getSelectionGroup() != null)
+ {
+ size = af.getViewport().getSelectionGroup().getSize();
+ }
+
+ /*
+ * disable calc options for which there is insufficient input data
+ * return value of true means enabled and selected
+ */
+ boolean checkPca = checkEnabled(pca, size, MIN_PCA_SELECTION);
+ boolean checkNeighbourJoining = checkEnabled(neighbourJoining, size,
+ MIN_TREE_SELECTION);
+ boolean checkAverageDistance = checkEnabled(averageDistance, size,
+ MIN_TREE_SELECTION);
+
+ if (checkPca || checkNeighbourJoining || checkAverageDistance)
+ {
+ calculate.setToolTipText(null);
+ calculate.setEnabled(true);
+ }
+ else
+ {
+ calculate.setEnabled(false);
+ }
+ updateScoreModels(modelNames, tips);
+ }
+
+ /**
+ * Check the input and disable a calculation's radio button if necessary. A
+ * tooltip is shown for disabled calculations.
+ *
+ * @param calc
+ * - radio button for the calculation being validated
+ * @param size
+ * - size of input to calculation
+ * @param minsize
+ * - minimum size for calculation
+ * @return true if size >= minsize and calc.isSelected
+ */
+ private boolean checkEnabled(JRadioButton calc, int size, int minsize)
+ {
+ String ttip = MessageManager.formatMessage(
+ "label.you_need_at_least_n_sequences", minsize);
+
+ calc.setEnabled(size >= minsize);
+ if (!calc.isEnabled())
+ {
+ calc.setToolTipText(ttip);
+ }
+ else
+ {
+ calc.setToolTipText(null);
+ }
+ if (calc.isSelected())
+ {
+ modelNames.setEnabled(calc.isEnabled());
+ if (calc.isEnabled())
+ {
+ return true;
+ }
+ else
+ {
+ calculate.setToolTipText(ttip);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A rather elaborate helper method (blame Swing, not me) that builds a
+ * drop-down list of score models (by name) with descriptions as tooltips.
+ * There is also a tooltip shown for the currently selected item when hovering
+ * over it (without opening the list).
+ */
+ protected JComboBox<String> buildModelOptionsList()
+ {
+ final JComboBox<String> scoreModelsCombo = new JComboBox<String>();
+ scoreModelsCombo.setRenderer(renderer);
+
+ /*
+ * show tooltip on mouse over the combobox
+ * note the listener has to be on the components that make up
+ * the combobox, doesn't work if just on the combobox
+ */
+ final MouseAdapter mouseListener = new MouseAdapter()
+ {
+ @Override
+ public void mouseEntered(MouseEvent e)
+ {
+ scoreModelsCombo.setToolTipText(tips.get(scoreModelsCombo.getSelectedIndex()));
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e)
+ {
+ scoreModelsCombo.setToolTipText(null);
+ }
+ };
+ for (Component c : scoreModelsCombo.getComponents())
+ {
+ c.addMouseListener(mouseListener);
+ }
+
+ updateScoreModels(scoreModelsCombo, tips);
+
+ /*
+ * set the list of tooltips on the combobox's renderer
+ */
+ renderer.setTooltips(tips);
+
+ return scoreModelsCombo;
+ }
+
+ private void updateScoreModels(JComboBox<String> comboBox,
+ List<String> toolTips)
+ {
+ Object curSel = comboBox.getSelectedItem();
+ toolTips.clear();
+ DefaultComboBoxModel<String> model = new DefaultComboBoxModel<String>();
+
+ /*
+ * now we can actually add entries to the combobox,
+ * remembering their descriptions for tooltips
+ */
+ ScoreModels scoreModels = ScoreModels.getInstance();
+ boolean selectedIsPresent = false;
+ for (ScoreModelI sm : scoreModels.getModels())
+ {
+ boolean nucleotide = af.getViewport().getAlignment().isNucleotide();
+ if (sm.isDNA() && nucleotide || sm.isProtein() && !nucleotide)
+ {
+ if (curSel != null && sm.getName().equals(curSel))
+ {
+ selectedIsPresent = true;
+ curSel = sm.getName();
+ }
+ model.addElement(sm.getName());
+
+ /*
+ * tooltip is description if provided, else text lookup with
+ * fallback on the model name
+ */
+ String tooltip = sm.getDescription();
+ if (tooltip == null)
+ {
+ tooltip = MessageManager.getStringOrReturn("label.score_model_",
+ sm.getName());
+ }
+ toolTips.add(tooltip);
+ }
+ }
+ if (selectedIsPresent)
+ {
+ model.setSelectedItem(curSel);
+ }
+ // finally, update the model
+ comboBox.setModel(model);
+ }
+
+ /**
+ * Open and calculate the selected tree or PCA on 'OK'
+ */
+ protected void calculate_actionPerformed()
+ {
+ boolean doPCA = pca.isSelected();
+ String modelName = modelNames.getSelectedItem().toString();
+ SimilarityParamsI params = getSimilarityParameters(doPCA);
+
+ if (doPCA)
+ {
+ openPcaPanel(modelName, params);
+ }
+ else
+ {
+ openTreePanel(modelName, params);
+ }
+
+ // closeFrame();
+ }
+
+ /**
+ * Open a new Tree panel on the desktop
+ *
+ * @param modelName
+ * @param params
+ */
+ protected void openTreePanel(String modelName, SimilarityParamsI params)
+ {
+ /*
+ * gui validation shouldn't allow insufficient sequences here, but leave
+ * this check in in case this method gets exposed programmatically in future
+ */
+ AlignViewport viewport = af.getViewport();
+ SequenceGroup sg = viewport.getSelectionGroup();
+ if (sg != null && sg.getSize() < MIN_TREE_SELECTION)
+ {
+ JvOptionPane
+ .showMessageDialog(
+ Desktop.desktop,
+ MessageManager
+ .formatMessage("label.you_need_at_least_n_sequences",
+ MIN_TREE_SELECTION),
+ MessageManager
+ .getString("label.not_enough_sequences"),
+ JvOptionPane.WARNING_MESSAGE);
+ return;
+ }
+
+ String treeType = neighbourJoining.isSelected() ? TreeBuilder.NEIGHBOUR_JOINING
+ : TreeBuilder.AVERAGE_DISTANCE;
+ af.newTreePanel(treeType, modelName, params);
+ }
+
+ /**
+ * Open a new PCA panel on the desktop
+ *
+ * @param modelName
+ * @param params
+ */
+ protected void openPcaPanel(String modelName, SimilarityParamsI params)
+ {
+ AlignViewport viewport = af.getViewport();
+
+ /*
+ * gui validation shouldn't allow insufficient sequences here, but leave
+ * this check in in case this method gets exposed programmatically in future
+ */
+ if (((viewport.getSelectionGroup() != null)
+ && (viewport.getSelectionGroup().getSize() < MIN_PCA_SELECTION) && (viewport
+ .getSelectionGroup().getSize() > 0))
+ || (viewport.getAlignment().getHeight() < MIN_PCA_SELECTION))
+ {
+ JvOptionPane.showInternalMessageDialog(this, MessageManager
+ .formatMessage("label.you_need_at_least_n_sequences",
+ MIN_PCA_SELECTION), MessageManager
+ .getString("label.sequence_selection_insufficient"),
+ JvOptionPane.WARNING_MESSAGE);
+ return;
+ }
+ new PCAPanel(af.alignPanel, modelName, params);
+ }
+
+ /**
+ *
+ */
+ protected void closeFrame()
+ {
+ try
+ {
+ frame.setClosed(true);
+ } catch (PropertyVetoException ex)
+ {
+ }
+ }
+
+ /**
+ * Returns a data bean holding parameters for similarity (or distance) model
+ * calculation
+ *
+ * @param doPCA
+ * @return
+ */
+ protected SimilarityParamsI getSimilarityParameters(boolean doPCA)
+ {
+ // commented out: parameter choices read from gui widgets
+ // SimilarityParamsI params = new SimilarityParams(
+ // includeGappedColumns.isSelected(), matchGaps.isSelected(),
+ // includeGaps.isSelected(), shorterSequence.isSelected());
+
+ boolean includeGapGap = true;
+ boolean includeGapResidue = true;
+ boolean matchOnShortestLength = false;
+
+ /*
+ * 'matchGaps' flag is only used in the PID calculation
+ * - set to false for PCA so that PCA using PID reproduces SeqSpace PCA
+ * - set to true for Tree to reproduce Jalview 2.10.1 calculation
+ * - set to false for Tree for a more correct calculation (JAL-374)
+ */
+ boolean matchGap = doPCA ? false : treeMatchGaps;
+
+ return new SimilarityParams(includeGapGap, matchGap, includeGapResidue, matchOnShortestLength);
+ }
+
+ /**
+ * Closes dialog on Close button press
+ */
+ protected void close_actionPerformed()
+ {
+ try
+ {
+ frame.setClosed(true);
+ } catch (Exception ex)
+ {
+ }
+ }
+}
savemenu.setVisible(false); // not yet implemented
viewMenu.add(fitToWindow);
- JMenuItem writeFeatures = new JMenuItem(
- MessageManager.getString("label.create_chimera_attributes"));
- writeFeatures.setToolTipText(MessageManager
- .getString("label.create_chimera_attributes_tip"));
- writeFeatures.addActionListener(new ActionListener()
+ /*
+ * exchange of Jalview features and Chimera attributes is for now
+ * an optionally enabled experimental feature
+ */
+ if (Desktop.instance.showExperimental())
{
- @Override
- public void actionPerformed(ActionEvent e)
+ JMenuItem writeFeatures = new JMenuItem(
+ MessageManager.getString("label.create_chimera_attributes"));
+ writeFeatures.setToolTipText(MessageManager
+ .getString("label.create_chimera_attributes_tip"));
+ writeFeatures.addActionListener(new ActionListener()
{
- sendFeaturesToChimera();
- }
- });
- viewerActionMenu.add(writeFeatures);
-
- final JMenu fetchAttributes = new JMenu(
- MessageManager.getString("label.fetch_chimera_attributes"));
- fetchAttributes.setToolTipText(MessageManager
- .getString("label.fetch_chimera_attributes_tip"));
- fetchAttributes.addMouseListener(new MouseAdapter()
- {
-
- @Override
- public void mouseEntered(MouseEvent e)
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ sendFeaturesToChimera();
+ }
+ });
+ viewerActionMenu.add(writeFeatures);
+
+ final JMenu fetchAttributes = new JMenu(
+ MessageManager.getString("label.fetch_chimera_attributes"));
+ fetchAttributes.setToolTipText(MessageManager
+ .getString("label.fetch_chimera_attributes_tip"));
+ fetchAttributes.addMouseListener(new MouseAdapter()
{
- buildAttributesMenu(fetchAttributes);
- }
- });
- viewerActionMenu.add(fetchAttributes);
+ @Override
+ public void mouseEntered(MouseEvent e)
+ {
+ buildAttributesMenu(fetchAttributes);
+ }
+ });
+ viewerActionMenu.add(fetchAttributes);
+ }
}
/**
{
public interface ColourChangeListener
{
+ /**
+ * Change colour scheme to the selected scheme
+ *
+ * @param name
+ * the registered (unique) name of a colour scheme
+ */
void changeColour_actionPerformed(String name);
}
* <li>Clustal</li>
* <li>...other 'built-in' colours</li>
* <li>...any user-defined colours</li>
- * <li>User Defined..</li>
+ * <li>User Defined..(only for AlignFrame menu)</li>
* </ul>
*
* @param colourMenu
}
/*
- * scan registered colour schemes (built-in or user-defined
+ * scan registered colour schemes (built-in or user-defined)
* and add them to the menu (in the order they were registered)
*/
Iterable<ColourSchemeI> colourSchemes = ColourSchemes.getInstance()
/*
* user-defined colour scheme loaded on startup or during the
* Jalview session; right-click on this offers the option to
- * remove it as a colour choice
+ * remove it as a colour choice (unless currently selected)
*/
radioItem.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent evt)
{
- if (evt.isPopupTrigger()) // Mac
+ if (evt.isPopupTrigger() && !radioItem.isSelected()) // Mac
{
offerRemoval();
}
@Override
public void mouseReleased(MouseEvent evt)
{
- if (evt.isPopupTrigger()) // Windows
+ if (evt.isPopupTrigger() && !radioItem.isSelected()) // Windows
{
offerRemoval();
}
final String label = MessageManager.getString("action.user_defined");
JRadioButtonMenuItem userDefinedColour = new JRadioButtonMenuItem(
label);
+ userDefinedColour.setName(ResidueColourScheme.USER_DEFINED);
userDefinedColour.addActionListener(new ActionListener()
{
@Override
}
/**
- * Marks as selected the colour menu item matching the given name, or the
- * first item ('None') if no match is found
+ * Marks as selected the colour menu item matching the given colour scheme, or
+ * the first item ('None') if no match is found. If the colour scheme is a
+ * user defined scheme, but not in the menu (this arises if a new scheme is
+ * defined and applied but not saved to file), then menu option
+ * "User Defined.." is selected.
*
* @param colourMenu
- * @param colourName
+ * @param cs
*/
- public static void setColourSelected(JMenu colourMenu, String colourName)
+ public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
{
- if (colourName == null)
- {
- return;
- }
+ String colourName = cs == null ? ResidueColourScheme.NONE : cs
+ .getSchemeName();
JRadioButtonMenuItem none = null;
+ JRadioButtonMenuItem userDefined = null;
/*
* select the radio button whose name matches the colour name
{
if (menuItem instanceof JRadioButtonMenuItem)
{
- String buttonName = ((JRadioButtonMenuItem) menuItem).getName();
- if (colourName.equals(buttonName))
+ JRadioButtonMenuItem radioButton = (JRadioButtonMenuItem) menuItem;
+ String buttonName = radioButton.getName();
+ if (buttonName.equals(colourName))
{
- ((JRadioButtonMenuItem) menuItem).setSelected(true);
+ radioButton.setSelected(true);
return;
}
if (ResidueColourScheme.NONE.equals(buttonName))
{
- none = (JRadioButtonMenuItem) menuItem;
+ none = radioButton;
+ }
+ if (ResidueColourScheme.USER_DEFINED.equals(buttonName))
+ {
+ userDefined = radioButton;
}
}
}
- if (none != null)
+
+ /*
+ * no match by name; select User Defined.. if current scheme is a
+ * user defined one, else select None
+ */
+ if (cs instanceof UserColourScheme && userDefined != null)
+ {
+ userDefined.setSelected(true);
+ }
+ else if (none != null)
{
none.setSelected(true);
}
}
/**
- * Marks as selected the colour menu item matching the given colour scheme, or
- * the first item ('None') if no match is found
- *
- * @param colourMenu
- * @param cs
- */
- public static void setColourSelected(JMenu colourMenu, ColourSchemeI cs)
- {
- setColourSelected(colourMenu, cs == null ? ResidueColourScheme.NONE
- : cs.getSchemeName());
- }
-
- /**
* Updates the USER_DEFINE_COLOURS preference to remove any de-registered
* colour scheme
*/
--- /dev/null
+package jalview.gui;
+
+import java.awt.Component;
+import java.util.List;
+
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.JComponent;
+import javax.swing.JList;
+
+/**
+ * A helper class to render a combobox with tooltips
+ *
+ * @see http
+ * ://stackoverflow.com/questions/480261/java-swing-mouseover-text-on-jcombobox
+ * -items
+ */
+public class ComboBoxTooltipRenderer extends DefaultListCellRenderer
+{
+ private static final long serialVersionUID = 1L;
+
+ List<String> tooltips;
+
+ @Override
+ public Component getListCellRendererComponent(JList list, Object value,
+ int index, boolean isSelected, boolean cellHasFocus)
+ {
+
+ JComponent comp = (JComponent) super.getListCellRendererComponent(list,
+ value, index, isSelected, cellHasFocus);
+
+ if (-1 < index && null != value && null != tooltips)
+ {
+ list.setToolTipText(tooltips.get(index));
+ }
+ return comp;
+ }
+
+ public void setTooltips(List<String> tips)
+ {
+ this.tooltips = tips;
+ }
+}
// are we attached to some parent Desktop
Desktop parent = null;
+ private int MIN_WIDTH = 300;
+
+ private int MIN_HEIGHT = 250;
+
public Console()
{
// create all components and add them
.getLocalGraphicsEnvironment();
String[] fontNames = ge.getAvailableFontFamilyNames();
for (int n = 0; n < fontNames.length; n++)
+ {
System.out.println(fontNames[n]);
+ }
// Testing part: simple an error thrown anywhere in this JVM will be printed
// on the Console
// We do it with a seperate Thread becasue we don't wan't to break a Thread
JFrame frame = new JFrame(string);
frame.setName(string);
if (x == -1)
- x = (int) (i / 2);
+ {
+ x = i / 2;
+ }
if (y == -1)
- y = (int) (j / 2);
+ {
+ y = j / 2;
+ }
frame.setBounds(x, y, i, j);
return frame;
}
frame = initFrame("Jalview Java Console", bounds.width,
bounds.height, bounds.x, bounds.y);
}
+ frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
// desktop.add(frame);
initConsole(false);
JalviewAppender jappender = new JalviewAppender();
// System.exit(0);
}
+ @Override
public synchronized void windowClosed(WindowEvent evt)
{
frame.setVisible(false);
}
}
+ @Override
public synchronized void windowClosing(WindowEvent evt)
{
frame.setVisible(false); // default behaviour of JFrame
// frame.dispose();
}
+ @Override
public synchronized void actionPerformed(ActionEvent evt)
{
trimBuffer(true);
// textArea.setText("");
}
+ @Override
public synchronized void run()
{
try
// lines++;
}
if (quit)
+ {
return;
+ }
}
while (Thread.currentThread() == reader2)
// lines++;
}
if (quit)
+ {
return;
+ }
}
while (Thread.currentThread() == textAppender)
{
long time = System.nanoTime();
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
+ @Override
public void run()
{
displayPipe.append(input); // change to stringBuffer
{
int available = in.available();
if (available == 0)
+ {
break;
+ }
byte b[] = new byte[available];
in.read(b);
input = input + new String(b, 0, b.length);
import jalview.api.FeaturesSourceI;
import jalview.bin.Jalview;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceI;
import jalview.io.AlignmentFileReaderI;
import jalview.io.AppletFormatAdapter;
AlignFrame af;
if (source instanceof ComplexAlignFile)
{
- ColumnSelection colSel = ((ComplexAlignFile) source)
- .getColumnSelection();
+ HiddenColumns hidden = ((ComplexAlignFile) source)
+ .getHiddenColumns();
SequenceI[] hiddenSeqs = ((ComplexAlignFile) source)
.getHiddenSequences();
boolean showSeqFeatures = ((ComplexAlignFile) source)
.getGlobalColourScheme();
FeaturesDisplayedI fd = ((ComplexAlignFile) source)
.getDisplayedFeatures();
- af = new AlignFrame(al, hiddenSeqs, colSel,
+ af = new AlignFrame(al, hiddenSeqs, hidden,
AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
af.getViewport().setShowSequenceFeatures(showSeqFeatures);
af.getViewport().setFeaturesDisplayed(fd);
DropTargetListener, ClipboardOwner, IProgressIndicator,
jalview.api.StructureSelectionManagerProvider
{
+ private static int DEFAULT_MIN_WIDTH = 300;
+
+ private static int DEFAULT_MIN_HEIGHT = 250;
+
+ private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES";
private JalviewChangeSupport changeSupport = new JalviewChangeSupport();
instance = this;
doVamsasClientCheck();
- groovyShell = new JMenuItem();
- groovyShell.setText(MessageManager.getString("label.groovy_console"));
- groovyShell.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- groovyShell_actionPerformed();
- }
- });
- toolsMenu.add(groovyShell);
- groovyShell.setVisible(true);
-
doConfigureStructurePrefs();
setTitle("Jalview " + jalview.bin.Cache.getProperty("VERSION"));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
showConsole(showjconsole);
showNews.setVisible(false);
+
+ experimentalFeatures.setSelected(showExperimental());
getIdentifiersOrgData();
});
}
+ /**
+ * Answers true if user preferences to enable experimental features is True
+ * (on), else false
+ *
+ * @return
+ */
+ public boolean showExperimental()
+ {
+ String experimental = Cache.getDefault(EXPERIMENTAL_FEATURES,
+ Boolean.FALSE.toString());
+ return Boolean.valueOf(experimental).booleanValue();
+ }
+
public void doConfigureStructurePrefs()
{
// configure services
openFrameCount++;
+ frame.setMinimumSize(new Dimension(DEFAULT_MIN_WIDTH,
+ DEFAULT_MIN_HEIGHT));
frame.setVisible(makeVisible);
frame.setClosable(true);
frame.setResizable(resizable);
}
- protected JMenuItem groovyShell;
-
/**
* Accessor method to quickly get all the AlignmentFrames loaded.
*
/**
* Add Groovy Support to Jalview
*/
+ @Override
public void groovyShell_actionPerformed()
{
try
if (Cache.getDefault("SHOW_JWS2_SERVICES", true))
{
- if (jalview.ws.jws2.Jws2Discoverer.getDiscoverer().isRunning())
- {
- jalview.ws.jws2.Jws2Discoverer.getDiscoverer().setAborted(true);
- }
t2 = jalview.ws.jws2.Jws2Discoverer.getDiscoverer().startDiscoverer(
changeSupport);
-
}
Thread t3 = null;
{
}
}
}
+
+ /**
+ * Sets the Preferences property for experimental features to True or False
+ * depending on the state of the controlling menu item
+ */
+ @Override
+ protected void showExperimental_actionPerformed(boolean selected)
+ {
+ Cache.setProperty(EXPERIMENTAL_FEATURES, Boolean.toString(selected));
+ }
}
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
+import jalview.io.FeaturesFile;
import jalview.schemes.FeatureColour;
import jalview.util.ColorUtils;
import jalview.util.MessageManager;
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.List;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
/**
* DOCUMENT ME!
public class FeatureRenderer extends
jalview.renderer.seqfeatures.FeatureRenderer
{
+ /*
+ * defaults for creating a new feature are the last created
+ * feature type and group
+ */
+ static String lastFeatureAdded = "feature_1";
+
+ static String lastFeatureGroupAdded = "Jalview";
+
Color resBoxColour;
AlignmentPanel ap;
/**
- * Creates a new FeatureRenderer object.
+ * Creates a new FeatureRenderer object
*
- * @param av
- * DOCUMENT ME!
+ * @param alignPanel
*/
- public FeatureRenderer(AlignmentPanel ap)
+ public FeatureRenderer(AlignmentPanel alignPanel)
{
- super(ap.av);
- this.ap = ap;
- if (ap != null && ap.getSeqPanel() != null
- && ap.getSeqPanel().seqCanvas != null
- && ap.getSeqPanel().seqCanvas.fr != null)
+ super(alignPanel.av);
+ this.ap = alignPanel;
+ if (alignPanel.getSeqPanel() != null
+ && alignPanel.getSeqPanel().seqCanvas != null
+ && alignPanel.getSeqPanel().seqCanvas.fr != null)
{
- transferSettings(ap.getSeqPanel().seqCanvas.fr);
+ transferSettings(alignPanel.getSeqPanel().seqCanvas.fr);
}
}
- // // /////////////
- // // Feature Editing Dialog
- // // Will be refactored in next release.
-
- static String lastFeatureAdded;
-
- static String lastFeatureGroupAdded;
-
- static String lastDescriptionAdded;
-
FeatureColourI oldcol, fcol;
int featureIndex = 0;
- boolean amendFeatures(final SequenceI[] sequences,
- final SequenceFeature[] features, boolean newFeatures,
- final AlignmentPanel ap)
+ /**
+ * Presents a dialog allowing the user to add new features, or amend or delete
+ * existing features. Currently this can be on
+ * <ul>
+ * <li>double-click on a sequence - Amend/Delete features at position</li>
+ * <li>Create sequence feature from pop-up menu on selected region</li>
+ * <li>Create features for pattern matches from Find</li>
+ * </ul>
+ * If the supplied feature type is null, show (and update on confirm) the type
+ * and group of the last new feature created (with initial defaults of
+ * "feature_1" and "Jalview").
+ *
+ * @param sequences
+ * the sequences features are to be created on (if creating
+ * features), or a single sequence (if amending features)
+ * @param features
+ * the current features at the position (if amending), or template
+ * new feature(s) with start/end position set (if creating)
+ * @param create
+ * true to create features, false to amend or delete
+ * @param alignPanel
+ * @return
+ */
+ protected boolean amendFeatures(final List<SequenceI> sequences,
+ final List<SequenceFeature> features, boolean create,
+ final AlignmentPanel alignPanel)
{
-
featureIndex = 0;
- final JPanel bigPanel = new JPanel(new BorderLayout());
- final JComboBox overlaps;
+ final JPanel mainPanel = new JPanel(new BorderLayout());
+
final JTextField name = new JTextField(25);
- final JTextField source = new JTextField(25);
+ name.getDocument().addDocumentListener(new DocumentListener()
+ {
+ @Override
+ public void insertUpdate(DocumentEvent e)
+ {
+ warnIfTypeHidden(mainPanel, name.getText());
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e)
+ {
+ warnIfTypeHidden(mainPanel, name.getText());
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e)
+ {
+ warnIfTypeHidden(mainPanel, name.getText());
+ }
+ });
+
+ final JTextField group = new JTextField(25);
+ group.getDocument().addDocumentListener(new DocumentListener()
+ {
+ @Override
+ public void insertUpdate(DocumentEvent e)
+ {
+ warnIfGroupHidden(mainPanel, group.getText());
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e)
+ {
+ warnIfGroupHidden(mainPanel, group.getText());
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e)
+ {
+ warnIfGroupHidden(mainPanel, group.getText());
+ }
+ });
+
final JTextArea description = new JTextArea(3, 25);
final JSpinner start = new JSpinner();
final JSpinner end = new JSpinner();
if (col != null)
{
fcol = new FeatureColour(col);
- updateColourButton(bigPanel, colour, new FeatureColour(col));
+ updateColourButton(mainPanel, colour, fcol);
}
}
else
{
if (fcc == null)
{
- final String type = features[featureIndex].getType();
+ final String ft = features.get(featureIndex).getType();
+ final String type = ft == null ? lastFeatureAdded : ft;
fcc = new FeatureColourChooser(me, type);
fcc.setRequestFocusEnabled(true);
fcc.requestFocus();
fcol = fcc.getLastColour();
fcc = null;
setColour(type, fcol);
- updateColourButton(bigPanel, colour, fcol);
+ updateColourButton(mainPanel, colour, fcol);
}
});
}
}
});
- JPanel tmp = new JPanel();
- JPanel panel = new JPanel(new GridLayout(3, 1));
+ JPanel gridPanel = new JPanel(new GridLayout(3, 1));
- // /////////////////////////////////////
- // /MULTIPLE FEATURES AT SELECTED RESIDUE
- if (!newFeatures && features.length > 1)
+ if (!create && features.size() > 1)
{
- panel = new JPanel(new GridLayout(4, 1));
- tmp = new JPanel();
- tmp.add(new JLabel(MessageManager.getString("label.select_feature")
+ /*
+ * more than one feature at selected position - add a drop-down
+ * to choose the feature to amend
+ */
+ gridPanel = new JPanel(new GridLayout(4, 1));
+ JPanel choosePanel = new JPanel();
+ choosePanel.add(new JLabel(MessageManager
+ .getString("label.select_feature")
+ ":"));
- overlaps = new JComboBox();
- for (int i = 0; i < features.length; i++)
+ final JComboBox<String> overlaps = new JComboBox<String>();
+ for (SequenceFeature sf : features)
{
- overlaps.addItem(features[i].getType() + "/"
- + features[i].getBegin() + "-" + features[i].getEnd()
- + " (" + features[i].getFeatureGroup() + ")");
+ String text = sf.getType() + "/" + sf.getBegin() + "-"
+ + sf.getEnd() + " (" + sf.getFeatureGroup() + ")";
+ overlaps.addItem(text);
}
-
- tmp.add(overlaps);
+ choosePanel.add(overlaps);
overlaps.addItemListener(new ItemListener()
{
if (index != -1)
{
featureIndex = index;
- name.setText(features[index].getType());
- description.setText(features[index].getDescription());
- source.setText(features[index].getFeatureGroup());
- start.setValue(new Integer(features[index].getBegin()));
- end.setValue(new Integer(features[index].getEnd()));
+ SequenceFeature sf = features.get(index);
+ name.setText(sf.getType());
+ description.setText(sf.getDescription());
+ group.setText(sf.getFeatureGroup());
+ start.setValue(new Integer(sf.getBegin()));
+ end.setValue(new Integer(sf.getEnd()));
SearchResultsI highlight = new SearchResults();
- highlight.addResult(sequences[0], features[index].getBegin(),
- features[index].getEnd());
+ highlight.addResult(sequences.get(0), sf.getBegin(),
+ sf.getEnd());
- ap.getSeqPanel().seqCanvas.highlightSearchResults(highlight);
+ alignPanel.getSeqPanel().seqCanvas.highlightSearchResults(highlight);
}
FeatureColourI col = getFeatureStyle(name.getText());
.createColourFromName(name.getText()));
}
oldcol = fcol = col;
- updateColourButton(bigPanel, colour, col);
+ updateColourButton(mainPanel, colour, col);
}
});
- panel.add(tmp);
+ gridPanel.add(choosePanel);
}
- // ////////
- // ////////////////////////////////////
- tmp = new JPanel();
- panel.add(tmp);
- tmp.add(new JLabel(MessageManager.getString("label.name:"),
+ JPanel namePanel = new JPanel();
+ gridPanel.add(namePanel);
+ namePanel.add(new JLabel(MessageManager.getString("label.name:"),
JLabel.RIGHT));
- tmp.add(name);
+ namePanel.add(name);
- tmp = new JPanel();
- panel.add(tmp);
- tmp.add(new JLabel(MessageManager.getString("label.group:"),
+ JPanel groupPanel = new JPanel();
+ gridPanel.add(groupPanel);
+ groupPanel.add(new JLabel(MessageManager.getString("label.group:"),
JLabel.RIGHT));
- tmp.add(source);
+ groupPanel.add(group);
- tmp = new JPanel();
- panel.add(tmp);
- tmp.add(new JLabel(MessageManager.getString("label.colour"),
+ JPanel colourPanel = new JPanel();
+ gridPanel.add(colourPanel);
+ colourPanel.add(new JLabel(MessageManager.getString("label.colour"),
JLabel.RIGHT));
- tmp.add(colour);
+ colourPanel.add(colour);
colour.setPreferredSize(new Dimension(150, 15));
colour.setFont(new java.awt.Font("Verdana", Font.PLAIN, 9));
colour.setForeground(Color.black);
colour.setVerticalAlignment(SwingConstants.CENTER);
colour.setHorizontalTextPosition(SwingConstants.CENTER);
colour.setVerticalTextPosition(SwingConstants.CENTER);
- bigPanel.add(panel, BorderLayout.NORTH);
+ mainPanel.add(gridPanel, BorderLayout.NORTH);
- panel = new JPanel();
- panel.add(new JLabel(MessageManager.getString("label.description:"),
+ JPanel descriptionPanel = new JPanel();
+ descriptionPanel.add(new JLabel(MessageManager
+ .getString("label.description:"),
JLabel.RIGHT));
description.setFont(JvSwingUtils.getTextAreaFont());
description.setLineWrap(true);
- panel.add(new JScrollPane(description));
+ descriptionPanel.add(new JScrollPane(description));
- if (!newFeatures)
+ if (!create)
{
- bigPanel.add(panel, BorderLayout.SOUTH);
+ mainPanel.add(descriptionPanel, BorderLayout.SOUTH);
- panel = new JPanel();
- panel.add(new JLabel(MessageManager.getString("label.start"),
+ JPanel startEndPanel = new JPanel();
+ startEndPanel.add(new JLabel(MessageManager.getString("label.start"),
JLabel.RIGHT));
- panel.add(start);
- panel.add(new JLabel(MessageManager.getString("label.end"),
+ startEndPanel.add(start);
+ startEndPanel.add(new JLabel(MessageManager.getString("label.end"),
JLabel.RIGHT));
- panel.add(end);
- bigPanel.add(panel, BorderLayout.CENTER);
+ startEndPanel.add(end);
+ mainPanel.add(startEndPanel, BorderLayout.CENTER);
}
else
{
- bigPanel.add(panel, BorderLayout.CENTER);
+ mainPanel.add(descriptionPanel, BorderLayout.CENTER);
}
- if (lastFeatureAdded == null)
- {
- if (features[0].type != null)
- {
- lastFeatureAdded = features[0].type;
- }
- else
- {
- lastFeatureAdded = "feature_1";
- }
- }
-
- if (lastFeatureGroupAdded == null)
- {
- if (features[0].featureGroup != null)
- {
- lastFeatureGroupAdded = features[0].featureGroup;
- }
- else
- {
- lastFeatureGroupAdded = "Jalview";
- }
- }
-
- if (newFeatures)
- {
- name.setText(lastFeatureAdded);
- source.setText(lastFeatureGroupAdded);
- }
- else
- {
- name.setText(features[0].getType());
- source.setText(features[0].getFeatureGroup());
- }
-
- start.setValue(new Integer(features[0].getBegin()));
- end.setValue(new Integer(features[0].getEnd()));
- description.setText(features[0].getDescription());
- updateColourButton(bigPanel, colour,
- (oldcol = fcol = getFeatureStyle(name.getText())));
+ /*
+ * default feature type and group to that of the first feature supplied,
+ * or to the last feature created if not supplied (null value)
+ */
+ SequenceFeature firstFeature = features.get(0);
+ boolean useLastDefaults = firstFeature.getType() == null;
+ final String featureType = useLastDefaults ? lastFeatureAdded
+ : firstFeature.getType();
+ final String featureGroup = useLastDefaults ? lastFeatureGroupAdded
+ : firstFeature.getFeatureGroup();
+ name.setText(featureType);
+ group.setText(featureGroup);
+
+ start.setValue(new Integer(firstFeature.getBegin()));
+ end.setValue(new Integer(firstFeature.getEnd()));
+ description.setText(firstFeature.getDescription());
+ updateColourButton(mainPanel, colour,
+ (oldcol = fcol = getFeatureStyle(featureType)));
Object[] options;
- if (!newFeatures)
+ if (!create)
{
- options = new Object[] { "Amend", "Delete", "Cancel" };
+ options = new Object[] { MessageManager.getString("label.amend"),
+ MessageManager.getString("action.delete"),
+ MessageManager.getString("action.cancel") };
}
else
{
- options = new Object[] { "OK", "Cancel" };
+ options = new Object[] { MessageManager.getString("action.ok"),
+ MessageManager.getString("action.cancel") };
}
- String title = newFeatures ? MessageManager
+ String title = create ? MessageManager
.getString("label.create_new_sequence_features")
: MessageManager.formatMessage("label.amend_delete_features",
- new String[] { sequences[0].getName() });
+ new String[] { sequences.get(0).getName() });
+ /*
+ * show the dialog
+ */
int reply = JvOptionPane.showInternalOptionDialog(Desktop.desktop,
- bigPanel, title, JvOptionPane.YES_NO_CANCEL_OPTION,
+ mainPanel, title, JvOptionPane.YES_NO_CANCEL_OPTION,
JvOptionPane.QUESTION_MESSAGE, null, options,
MessageManager.getString("action.ok"));
- jalview.io.FeaturesFile ffile = new jalview.io.FeaturesFile();
+ FeaturesFile ffile = new FeaturesFile();
- if (reply == JvOptionPane.OK_OPTION && name.getText().length() > 0)
+ String enteredType = name.getText().trim();
+ if (reply == JvOptionPane.OK_OPTION && enteredType.length() > 0)
{
- lastFeatureAdded = name.getText().trim();
- lastFeatureGroupAdded = source.getText().trim();
- lastDescriptionAdded = description.getText().replaceAll("\n", " ");
- // TODO: determine if the null feature group is valid
- if (lastFeatureGroupAdded.length() < 1)
+ /*
+ * update default values only if creating using default values
+ */
+ if (useLastDefaults)
{
- lastFeatureGroupAdded = null;
+ lastFeatureAdded = enteredType;
+ lastFeatureGroupAdded = group.getText().trim();
+ // TODO: determine if the null feature group is valid
+ if (lastFeatureGroupAdded.length() < 1)
+ {
+ lastFeatureGroupAdded = null;
+ }
}
}
- if (!newFeatures)
+ if (!create)
{
- SequenceFeature sf = features[featureIndex];
+ SequenceFeature sf = features.get(featureIndex);
if (reply == JvOptionPane.NO_OPTION)
{
- sequences[0].getDatasetSequence().deleteFeature(sf);
+ /*
+ * NO_OPTION corresponds to the Delete button
+ */
+ sequences.get(0).getDatasetSequence().deleteFeature(sf);
+ // update Feature Settings for removal of feature / group
+ featuresAdded();
}
else if (reply == JvOptionPane.YES_OPTION)
{
- sf.type = lastFeatureAdded;
- sf.featureGroup = lastFeatureGroupAdded;
- sf.description = lastDescriptionAdded;
+ /*
+ * YES_OPTION corresponds to the Amend button
+ * need to refresh Feature Settings if type, group or colour changed
+ */
+ sf.type = enteredType;
+ sf.featureGroup = group.getText().trim();
+ sf.description = description.getText().replaceAll("\n", " ");
+ boolean refreshSettings = (!featureType.equals(sf.type) || !featureGroup
+ .equals(sf.featureGroup));
+ refreshSettings |= (fcol != oldcol);
setColour(sf.type, fcol);
- getFeaturesDisplayed().setVisible(sf.type);
try
{
}
ffile.parseDescriptionHTML(sf, false);
+ if (refreshSettings)
+ {
+ featuresAdded();
+ }
}
}
else
// NEW FEATURES ADDED
{
- if (reply == JvOptionPane.OK_OPTION && lastFeatureAdded.length() > 0)
+ if (reply == JvOptionPane.OK_OPTION && enteredType.length() > 0)
{
- for (int i = 0; i < sequences.length; i++)
+ for (int i = 0; i < sequences.size(); i++)
{
- features[i].type = lastFeatureAdded;
+ SequenceFeature sf = features.get(i);
+ sf.type = enteredType;
// 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);
+ sf.featureGroup = group.getText().trim();
+ sf.description = description.getText().replaceAll("\n", " ");
+ sequences.get(i).addSequenceFeature(sf);
+ ffile.parseDescriptionHTML(sf, false);
}
- if (lastFeatureGroupAdded != null)
- {
- setGroupVisibility(lastFeatureGroupAdded, true);
- }
- setColour(lastFeatureAdded, fcol);
- setVisible(lastFeatureAdded);
+ setColour(enteredType, fcol);
- findAllFeatures(false);
+ featuresAdded();
- ap.paintAlignment(true);
+ alignPanel.paintAlignment(true);
return true;
}
}
}
- ap.paintAlignment(true);
+ alignPanel.paintAlignment(true);
return true;
}
/**
+ * Show a warning message if the entered type is one that is currently hidden
+ *
+ * @param panel
+ * @param type
+ */
+ protected void warnIfTypeHidden(JPanel panel, String type)
+ {
+ if (getRenderOrder().contains(type))
+ {
+ if (!showFeatureOfType(type))
+ {
+ String msg = MessageManager.formatMessage("label.warning_hidden",
+ MessageManager.getString("label.feature_type"), type);
+ JvOptionPane.showMessageDialog(panel, msg, "",
+ JvOptionPane.OK_OPTION);
+ }
+ }
+ }
+
+ /**
+ * Show a warning message if the entered group is one that is currently hidden
+ *
+ * @param panel
+ * @param group
+ */
+ protected void warnIfGroupHidden(JPanel panel, String group)
+ {
+ if (featureGroups.containsKey(group) && !featureGroups.get(group))
+ {
+ String msg = MessageManager.formatMessage("label.warning_hidden",
+ MessageManager.getString("label.group"), group);
+ JvOptionPane.showMessageDialog(panel, msg, "", JvOptionPane.OK_OPTION);
+ }
+ }
+
+ /**
* update the amend feature button dependent on the given style
*
* @param bigPanel
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
+import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
JPanel transPanel = new JPanel(new GridLayout(1, 2));
+ private static final int MIN_WIDTH = 400;
+
+ private static final int MIN_HEIGHT = 400;
+
+ /**
+ * Constructor
+ *
+ * @param af
+ */
public FeatureSettings(AlignFrame af)
{
this.af = af;
MessageManager.getString("label.sequence_feature_settings"),
400, 450);
}
+ frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
frame.addInternalFrameListener(new javax.swing.event.InternalFrameAdapter()
{
{
boolean visible = fr.checkGroupVisibility(group, true);
- if (groupPanel == null)
- {
- groupPanel = new JPanel();
- }
-
- boolean alreadyAdded = false;
for (int g = 0; g < groupPanel.getComponentCount(); g++)
{
if (((JCheckBox) groupPanel.getComponent(g)).getText().equals(group))
{
- alreadyAdded = true;
((JCheckBox) groupPanel.getComponent(g)).setSelected(visible);
- break;
+ return visible;
}
}
- if (alreadyAdded)
- {
-
- return visible;
- }
final String grp = group;
final JCheckBox check = new JCheckBox(group, visible);
check.setFont(new Font("Serif", Font.BOLD, 12));
SequenceFeature[] tmpfeatures;
String group = null, type;
Vector<String> visibleChecks = new Vector<String>();
+ Set<String> foundGroups = new HashSet<String>();
// Find out which features should be visible depending on which groups
// are selected / deselected
while (index < tmpfeatures.length)
{
group = tmpfeatures[index].featureGroup;
+ foundGroups.add(group);
if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
{
System.arraycopy(data[i], 0, originalData[i], 0, 3);
}
}
+ else
+ {
+ updateOriginalData(data);
+ }
table.setModel(new FeatureTableModel(data));
table.getColumnModel().getColumn(0).setPreferredWidth(200);
- if (groupPanel != null)
- {
- groupPanel.setLayout(new GridLayout(
- fr.getFeatureGroupsSize() / 4 + 1, 4));
-
- groupPanel.validate();
- bigPanel.add(groupPanel, BorderLayout.NORTH);
- }
+ groupPanel.setLayout(new GridLayout(fr.getFeatureGroupsSize() / 4 + 1,
+ 4));
+ pruneGroups(foundGroups);
+ groupPanel.validate();
updateFeatureRenderer(data, groupChanged != null);
resettingTable = false;
}
/**
+ * Updates 'originalData' (used for restore on Cancel) if we detect that
+ * changes have been made outwith this dialog
+ * <ul>
+ * <li>a new feature type added (and made visible)</li>
+ * <li>a feature colour changed (in the Amend Features dialog)</li>
+ * </ul>
+ *
+ * @param foundData
+ */
+ protected void updateOriginalData(Object[][] foundData)
+ {
+ // todo LinkedHashMap instead of Object[][] would be nice
+
+ Object[][] currentData = ((FeatureTableModel) table.getModel())
+ .getData();
+ for (Object[] row : foundData)
+ {
+ String type = (String) row[0];
+ boolean found = false;
+ for (Object[] current : currentData)
+ {
+ if (type.equals(current[0]))
+ {
+ found = true;
+ /*
+ * currently dependent on object equality here;
+ * really need an equals method on FeatureColour
+ */
+ if (!row[1].equals(current[1]))
+ {
+ /*
+ * feature colour has changed externally - update originalData
+ */
+ for (Object[] original : originalData)
+ {
+ if (type.equals(original[0]))
+ {
+ original[1] = row[1];
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ if (!found)
+ {
+ /*
+ * new feature detected - add to original data (on top)
+ */
+ Object[][] newData = new Object[originalData.length + 1][3];
+ for (int i = 0; i < originalData.length; i++)
+ {
+ System.arraycopy(originalData[i], 0, newData[i + 1], 0, 3);
+ }
+ newData[0] = row;
+ originalData = newData;
+ }
+ }
+ }
+
+ /**
+ * Remove from the groups panel any checkboxes for groups that are not in the
+ * foundGroups set. This enables removing a group from the display when the
+ * last feature in that group is deleted.
+ *
+ * @param foundGroups
+ */
+ protected void pruneGroups(Set<String> foundGroups)
+ {
+ for (int g = 0; g < groupPanel.getComponentCount(); g++)
+ {
+ JCheckBox checkbox = (JCheckBox) groupPanel.getComponent(g);
+ if (!foundGroups.contains(checkbox.getText()))
+ {
+ groupPanel.remove(checkbox);
+ }
+ }
+ }
+
+ /**
* reorder data based on the featureRenderers global priority list.
*
* @param data
settingsPane.setLayout(borderLayout2);
dasSettingsPane.setLayout(borderLayout3);
bigPanel.setLayout(borderLayout4);
+
+ groupPanel = new JPanel();
+ bigPanel.add(groupPanel, BorderLayout.NORTH);
+
invert.setFont(JvSwingUtils.getLabelFont());
invert.setText(MessageManager.getString("label.invert_selection"));
invert.addActionListener(new ActionListener()
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
+import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Vector;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
*/
public class Finder extends GFinder
{
- private static final int HEIGHT = 110;
+ private static final int MY_HEIGHT = 120;
- private static final int WIDTH = 340;
+ private static final int MY_WIDTH = 400;
AlignmentViewport av;
AlignmentPanel ap;
+ private static final int MIN_WIDTH = 350;
+
+ private static final int MIN_HEIGHT = 120;
+
JInternalFrame frame;
int seqIndex = 0;
});
addEscapeHandler();
Desktop.addInternalFrame(frame, MessageManager.getString("label.find"),
- WIDTH, HEIGHT);
-
+ MY_WIDTH, MY_HEIGHT);
+ frame.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
searchBox.requestFocus();
}
JInternalFrame[] frames = Desktop.desktop.getAllFrames();
for (int f = 0; f < frames.length; f++)
{
- JInternalFrame frame = frames[f];
- if (frame != null && frame instanceof AlignFrame)
+ JInternalFrame alignFrame = frames[f];
+ if (alignFrame != null && alignFrame instanceof AlignFrame)
{
- av = ((AlignFrame) frame).viewport;
- ap = ((AlignFrame) frame).alignPanel;
+ av = ((AlignFrame) alignFrame).viewport;
+ ap = ((AlignFrame) alignFrame).alignPanel;
return true;
}
}
}
/**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
+ * Opens a dialog that allows the user to create sequence features for the
+ * find match results.
*/
@Override
- public void createNewGroup_actionPerformed(ActionEvent e)
+ public void createFeatures_actionPerformed()
{
- SequenceI[] seqs = new SequenceI[searchResults.getSize()];
- SequenceFeature[] features = new SequenceFeature[searchResults
- .getSize()];
+ List<SequenceI> seqs = new ArrayList<SequenceI>();
+ List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+
+ String searchString = searchBox.getEditor().getItem().toString().trim();
+ String desc = "Search Results";
- int i = 0;
+ /*
+ * assemble dataset sequences, and template new sequence features,
+ * for the amend features dialog
+ */
for (SearchResultMatchI match : searchResults.getResults())
{
- seqs[i] = match.getSequence().getDatasetSequence();
-
- features[i] = new SequenceFeature(searchBox.getEditor().getItem()
- .toString().trim(),
- "Search Results", null, match.getStart(), match.getEnd(),
- "Search Results");
- i++;
+ seqs.add(match.getSequence().getDatasetSequence());
+ features.add(new SequenceFeature(searchString, desc, null, match
+ .getStart(), match.getEnd(), desc));
}
if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(seqs,
features, true, ap))
{
+ /*
+ * ensure feature display is turned on to show the new features,
+ * and remove them as highlighted regions
+ */
ap.alignFrame.showSeqFeatures.setSelected(true);
av.setShowSequenceFeatures(true);
ap.highlightSearchResults(null);
* Search the alignment for the next or all matches. If 'all matches', a
* dialog is shown with the number of sequence ids and subsequences matched.
*
- * @param findAll
+ * @param doFindAll
*/
- void doSearch(boolean findAll)
+ void doSearch(boolean doFindAll)
{
- createNewGroup.setEnabled(false);
+ createFeatures.setEnabled(false);
String searchString = searchBox.getUserInput().trim();
finder.setCaseSensitive(caseSensitive.isSelected());
finder.setIncludeDescription(searchDescription.isSelected());
- finder.setFindAll(findAll);
+ finder.setFindAll(doFindAll);
finder.find(searchString); // returns true if anything was actually found
if (searchResults.getSize() > 0)
{
haveResults = true;
- createNewGroup.setEnabled(true);
+ createFeatures.setEnabled(true);
}
else
{
}
else
{
- if (findAll)
+ if (doFindAll)
{
// then we report the matches that were found
String message = (idMatch.size() > 0) ? "" + idMatch.size()
import java.awt.Font;
import java.awt.FontMetrics;
-import java.awt.event.ActionEvent;
import java.awt.geom.Rectangle2D;
import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
-import javax.swing.JOptionPane;
/**
* DOCUMENT ME!
*/
Font oldFont;
+ /*
+ * The font on opening the dialog (to be restored on Cancel)
+ * on the other half of a split frame (if applicable)
+ */
+ Font oldComplementFont;
+
+ /*
+ * the state of 'scale protein as cDNA' on opening the dialog
+ */
boolean oldProteinScale;
+ /*
+ * the state of 'same font for protein and cDNA' on opening the dialog
+ */
+ boolean oldMirrorFont;
+
boolean init = true;
JInternalFrame frame;
private boolean lastSelMono = false;
+ private boolean oldSmoothFont;
+
+ private boolean oldComplementSmooth;
+
/**
- * Creates a new FontChooser object.
+ * Creates a new FontChooser for a tree panel
*
- * @param ap
- * DOCUMENT ME!
+ * @param treePanel
*/
- public FontChooser(TreePanel tp)
+ public FontChooser(TreePanel treePanel)
{
- this.tp = tp;
- ap = tp.treeCanvas.ap;
- oldFont = tp.getTreeFont();
+ this.tp = treePanel;
+ ap = treePanel.treeCanvas.ap;
+ oldFont = treePanel.getTreeFont();
defaultButton.setVisible(false);
smoothFont.setEnabled(false);
init();
}
/**
- * Creates a new FontChooser object.
+ * Creates a new FontChooser for an alignment panel
*
- * @param ap
- * DOCUMENT ME!
+ * @param alignPanel
*/
- public FontChooser(AlignmentPanel ap)
+ public FontChooser(AlignmentPanel alignPanel)
{
- oldFont = ap.av.getFont();
- oldProteinScale = ap.av.isScaleProteinAsCdna();
-
- this.ap = ap;
+ oldFont = alignPanel.av.getFont();
+ oldProteinScale = alignPanel.av.isScaleProteinAsCdna();
+ oldMirrorFont = alignPanel.av.isProteinFontAsCdna();
+ oldSmoothFont = alignPanel.av.antiAlias;
+ this.ap = alignPanel;
init();
}
/*
* Enable 'scale protein as cDNA' in a SplitFrame view. The selection is
- * stored in the ViewStyle of both dna and protein Viewport
+ * stored in the ViewStyle of both dna and protein Viewport. Also enable
+ * checkbox for copy font changes to other half of split frame.
*/
- scaleAsCdna.setEnabled(false);
- if (ap.av.getCodingComplement() != null)
+ boolean inSplitFrame = ap.av.getCodingComplement() != null;
+ if (inSplitFrame)
{
- scaleAsCdna.setEnabled(true);
+ oldComplementFont = ((AlignViewport) ap.av.getCodingComplement())
+ .getFont();
+ oldComplementSmooth = ((AlignViewport) ap.av.getCodingComplement()).antiAlias;
scaleAsCdna.setVisible(true);
scaleAsCdna.setSelected(ap.av.isScaleProteinAsCdna());
+ fontAsCdna.setVisible(true);
+ fontAsCdna.setSelected(ap.av.isProteinFontAsCdna());
}
if (tp != null)
else
{
Desktop.addInternalFrame(frame,
- MessageManager.getString("action.change_font"), 380, 200,
+ MessageManager.getString("action.change_font"), 380, 220,
false);
}
}
@Override
- public void smoothFont_actionPerformed(ActionEvent e)
+ protected void smoothFont_actionPerformed()
{
ap.av.antiAlias = smoothFont.isSelected();
ap.getAnnotationPanel().image = null;
ap.paintAlignment(true);
+ if (ap.av.getCodingComplement() != null && ap.av.isProteinFontAsCdna())
+ {
+ ((AlignViewport) ap.av.getCodingComplement()).antiAlias = ap.av.antiAlias;
+ SplitFrame sv = (SplitFrame) ap.alignFrame.getSplitViewContainer();
+ sv.adjustLayout();
+ sv.repaint();
+ }
+
}
/**
* DOCUMENT ME!
*/
@Override
- protected void ok_actionPerformed(ActionEvent e)
+ protected void ok_actionPerformed()
{
try
{
* DOCUMENT ME!
*/
@Override
- protected void cancel_actionPerformed(ActionEvent e)
+ protected void cancel_actionPerformed()
{
if (ap != null)
{
ap.av.setFont(oldFont, true);
ap.av.setScaleProteinAsCdna(oldProteinScale);
+ ap.av.setProteinFontAsCdna(oldMirrorFont);
+ ap.av.antiAlias = oldSmoothFont;
ap.paintAlignment(true);
- if (scaleAsCdna.isEnabled())
+
+ if (scaleAsCdna.isVisible() && scaleAsCdna.isEnabled())
{
- ap.av.setScaleProteinAsCdna(oldProteinScale);
ap.av.getCodingComplement().setScaleProteinAsCdna(oldProteinScale);
+ ap.av.getCodingComplement().setProteinFontAsCdna(oldMirrorFont);
+ ((AlignViewport) ap.av.getCodingComplement()).antiAlias = oldComplementSmooth;
+ ap.av.getCodingComplement().setFont(oldComplementFont, true);
+ SplitFrame splitFrame = (SplitFrame) ap.alignFrame
+ .getSplitViewContainer();
+ splitFrame.adjustLayout();
+ splitFrame.repaint();
}
}
else if (tp != null)
{
tp.setTreeFont(oldFont);
}
- fontName.setSelectedItem(oldFont.getName());
- fontSize.setSelectedItem(oldFont.getSize());
- fontStyle.setSelectedIndex(oldFont.getStyle());
try
{
{
ap.av.setFont(newFont, true);
ap.fontChanged();
+
+ /*
+ * adjust other half of split frame if any, if either same
+ * font, or proportionate scaling, is selected
+ */
+ if (fontAsCdna.isEnabled())
+ {
+ if (fontAsCdna.isSelected())
+ {
+ /*
+ * copy the font
+ */
+ ap.av.getCodingComplement().setFont(newFont, true);
+ }
+
+ /*
+ * adjust layout for font change / reset / sizing
+ */
+ SplitFrame splitFrame = (SplitFrame) ap.alignFrame
+ .getSplitViewContainer();
+ splitFrame.adjustLayout();
+ splitFrame.repaint();
+ }
}
monospaced.setSelected(mw == iw);
}
/**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
+ * Updates on change of selected font name
*/
@Override
- protected void fontName_actionPerformed(ActionEvent e)
+ protected void fontName_actionPerformed()
{
if (init)
{
}
/**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
+ * Updates on change of selected font size
*/
@Override
- protected void fontSize_actionPerformed(ActionEvent e)
+ protected void fontSize_actionPerformed()
{
if (init)
{
}
/**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
+ * Updates on change of selected font style
*/
@Override
- protected void fontStyle_actionPerformed(ActionEvent e)
+ protected void fontStyle_actionPerformed()
{
if (init)
{
/**
* Make selected settings the defaults by storing them (via Cache class) in
* the .jalview_properties file (the file is only written when Jalview exits)
- *
- * @param e
*/
@Override
- public void defaultButton_actionPerformed(ActionEvent e)
+ public void defaultButton_actionPerformed()
{
Cache.setProperty("FONT_NAME", fontName.getSelectedItem().toString());
Cache.setProperty("FONT_STYLE", fontStyle.getSelectedIndex() + "");
* characters
*/
@Override
- protected void scaleAsCdna_actionPerformed(ActionEvent e)
+ protected void scaleAsCdna_actionPerformed()
{
ap.av.setScaleProteinAsCdna(scaleAsCdna.isSelected());
ap.av.getCodingComplement().setScaleProteinAsCdna(
.getSplitViewContainer();
splitFrame.adjustLayout();
splitFrame.repaint();
- // ap.paintAlignment(true);
- // TODO would like to repaint
+ }
+
+ /**
+ * Turn on/off mirroring of font across split frame. If turning on, also
+ * copies the current font across the split frame. If turning off, restores
+ * the other half of the split frame to its initial font.
+ */
+ @Override
+ protected void mirrorFonts_actionPerformed()
+ {
+ boolean selected = fontAsCdna.isSelected();
+ ap.av.setProteinFontAsCdna(selected);
+ ap.av.getCodingComplement().setProteinFontAsCdna(selected);
+
+ /*
+ * reset other half of split frame if turning option off
+ */
+ if (!selected)
+ {
+ ap.av.getCodingComplement().setFont(oldComplementFont, true);
+ }
+
+ changeFont();
}
}
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
int annotationHeight = 0;
private JLabel dbstatus, dbstatex;
+ private JPanel mainPanel = new JPanel(new BorderLayout());
+
public JDatabaseTree(jalview.ws.SequenceFetcher sfetch)
{
- initDialogFrame(this, true, false,
+ mainPanel.add(this);
+ initDialogFrame(mainPanel, true, false,
MessageManager
.getString("label.select_database_retrieval_source"),
650, 490);
}
// and sort the tree
sortTreeNodes(root);
- svp = new JScrollPane();
- // svp.setAutoscrolls(true);
dbviews = new JTree(new DefaultTreeModel(root, false));
dbviews.setCellRenderer(new DbTreeRenderer(this));
dbviews.getSelectionModel().setSelectionMode(
TreeSelectionModel.SINGLE_TREE_SELECTION);
- svp.getViewport().setView(dbviews);
- // svp.getViewport().setMinimumSize(new Dimension(300,200));
- // svp.setSize(300,250);
- // JPanel panel=new JPanel();
- // panel.setSize(new Dimension(350,220));
- // panel.add(svp);
+ svp = new JScrollPane(dbviews);
+ svp.setMinimumSize(new Dimension(100, 200));
+ svp.setPreferredSize(new Dimension(200, 400));
+ svp.setMaximumSize(new Dimension(300, 600));
+
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.setSize(new Dimension(350, 220));
+ panel.add(svp);
dbviews.addTreeSelectionListener(new TreeSelectionListener()
{
dbstat.add(dbstatex);
jc.add(dbstat, BorderLayout.SOUTH);
jc.validate();
- // j.setPreferredSize(new Dimension(300,50));
add(jc, BorderLayout.CENTER);
ok.setEnabled(false);
j.add(ok);
Tree tree = new Tree();
tree.setTitle(tp.getTitle());
tree.setCurrentTree((av.currentTree == tp.getTree()));
- tree.setNewick(tp.getTree().toString());
+ tree.setNewick(tp.getTree().print());
tree.setThreshold(tp.treeCanvas.threshold);
tree.setFitToWindow(tp.fitToWindow.getState());
if (av.hasHiddenColumns())
{
- if (av.getColumnSelection() == null
- || av.getColumnSelection().getHiddenColumns() == null)
+ jalview.datamodel.HiddenColumns hidden = av.getAlignment()
+ .getHiddenColumns();
+ if (hidden == null || hidden.getHiddenRegions() == null)
{
warn("REPORT BUG: avoided null columnselection bug (DMAM reported). Please contact Jim about this.");
}
else
{
- for (int c = 0; c < av.getColumnSelection().getHiddenColumns()
+ for (int c = 0; c < hidden.getHiddenRegions()
.size(); c++)
{
- int[] region = av.getColumnSelection().getHiddenColumns()
+ int[] region = hidden.getHiddenRegions()
.get(c);
HiddenColumns hc = new HiddenColumns();
hc.setStart(region[0]);
TreePanel tp = (TreePanel) retrieveExistingObj(tree.getId());
if (tp == null)
{
- tp = af.ShowNewickTree(
+ tp = af.showNewickTree(
new jalview.io.NewickFile(tree.getNewick()),
tree.getTitle(), tree.getWidth(), tree.getHeight(),
tree.getXpos(), tree.getYpos());
Tree tree = jms.getTree(t);
- TreePanel tp = af.ShowNewickTree(
+ TreePanel tp = af.showNewickTree(
new jalview.io.NewickFile(tree.getNewick()),
tree.getTitle(), tree.getWidth(), tree.getHeight(),
tree.getXpos(), tree.getYpos());
import jalview.util.MessageManager;
import java.awt.Container;
+import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
{
frame.setSize(width, height);
}
+ int minWidth = width - 100;
+ int minHeight = height - 100;
+ frame.setMinimumSize(new Dimension(minWidth, minHeight));
frame.setContentPane(content);
this.block = block;
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.gui;
+
+import jalview.api.AlignViewportI;
+import jalview.renderer.OverviewRenderer;
+import jalview.viewmodel.OverviewDimensions;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
+import javax.swing.JComponent;
+
+public class OverviewCanvas extends JComponent
+{
+ private static final Color TRANS_GREY = new Color(100, 100, 100, 25);
+
+ // This is set true if the alignment view changes whilst
+ // the overview is being calculated
+ private volatile boolean restart = false;
+
+ private volatile boolean updaterunning = false;
+
+ private BufferedImage miniMe;
+
+ private BufferedImage lastMiniMe = null;
+
+ // Can set different properties in this seqCanvas than
+ // main visible SeqCanvas
+ private SequenceRenderer sr;
+
+ private jalview.renderer.seqfeatures.FeatureRenderer fr;
+
+ private OverviewDimensions od;
+
+ private AlignViewportI av;
+
+ public OverviewCanvas(OverviewDimensions overviewDims,
+ AlignViewportI alignvp)
+ {
+ od = overviewDims;
+ av = alignvp;
+
+ sr = new SequenceRenderer(av);
+ sr.renderGaps = false;
+ sr.forOverview = true;
+ fr = new jalview.renderer.seqfeatures.FeatureRenderer(av);
+ }
+
+ /**
+ * Update the overview dimensions object used by the canvas (e.g. if we change
+ * from showing hidden columns to hiding them or vice versa)
+ *
+ * @param overviewDims
+ */
+ public void resetOviewDims(OverviewDimensions overviewDims)
+ {
+ od = overviewDims;
+ }
+
+ /**
+ * Signals to drawing code that the associated alignment viewport has changed
+ * and a redraw will be required
+ */
+ public boolean restartDraw()
+ {
+ synchronized (this)
+ {
+ if (updaterunning)
+ {
+ restart = true;
+ }
+ else
+ {
+ updaterunning = true;
+ }
+ return restart;
+ }
+ }
+
+ /**
+ * Draw the overview sequences
+ *
+ * @param showSequenceFeatures
+ * true if sequence features are to be shown
+ * @param showAnnotation
+ * true if the annotation is to be shown
+ * @param transferRenderer
+ * the renderer to transfer feature colouring from
+ */
+ public void draw(boolean showSequenceFeatures, boolean showAnnotation,
+ FeatureRenderer transferRenderer)
+ {
+ miniMe = null;
+
+ if (showSequenceFeatures)
+ {
+ fr.transferSettings(transferRenderer);
+ }
+
+ setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
+
+ OverviewRenderer or = new OverviewRenderer(sr, fr, od);
+ miniMe = or.draw(od.getRows(av.getAlignment()),
+ od.getColumns(av.getAlignment()));
+
+ Graphics mg = miniMe.getGraphics();
+
+ if (showAnnotation)
+ {
+ mg.translate(0, od.getSequencesHeight());
+ or.drawGraph(mg, av.getAlignmentConservationAnnotation(),
+ av.getCharWidth(), od.getGraphHeight(),
+ od.getColumns(av.getAlignment()));
+ mg.translate(0, -od.getSequencesHeight());
+ }
+ System.gc();
+
+ if (restart)
+ {
+ restart = false;
+ draw(showSequenceFeatures, showAnnotation, transferRenderer);
+ }
+ else
+ {
+ updaterunning = false;
+ lastMiniMe = miniMe;
+ }
+ }
+
+ @Override
+ public void paintComponent(Graphics g)
+ {
+ if (restart)
+ {
+ if (lastMiniMe == null)
+ {
+ g.setColor(Color.white);
+ g.fillRect(0, 0, getWidth(), getHeight());
+ }
+ else
+ {
+ g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
+ }
+ g.setColor(TRANS_GREY);
+ g.fillRect(0, 0, getWidth(), getHeight());
+ }
+ else if (lastMiniMe != null)
+ {
+ g.drawImage(lastMiniMe, 0, 0, this);
+ if (lastMiniMe != miniMe)
+ {
+ g.setColor(TRANS_GREY);
+ g.fillRect(0, 0, getWidth(), getHeight());
+ }
+ }
+
+ g.setColor(Color.red);
+ od.drawBox(g);
+ }
+
+}
*/
package jalview.gui;
-import jalview.datamodel.SequenceI;
-import jalview.renderer.AnnotationRenderer;
-import jalview.renderer.seqfeatures.FeatureColourFinder;
+import jalview.util.MessageManager;
+import jalview.util.Platform;
import jalview.viewmodel.OverviewDimensions;
+import jalview.viewmodel.OverviewDimensionsHideHidden;
+import jalview.viewmodel.OverviewDimensionsShowHidden;
-import java.awt.Color;
+import java.awt.BorderLayout;
import java.awt.Dimension;
-import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
-import java.awt.image.BufferedImage;
+import javax.swing.JCheckBoxMenuItem;
import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.SwingUtilities;
/**
* Panel displaying an overview of the full alignment, with an interactive box
*/
public class OverviewPanel extends JPanel implements Runnable
{
- private static final Color TRANS_GREY = new Color(100, 100, 100, 25);
-
- private final AnnotationRenderer renderer = new AnnotationRenderer();
-
private OverviewDimensions od;
- private BufferedImage miniMe;
-
- private BufferedImage lastMiniMe = null;
+ private OverviewCanvas oviewCanvas;
private AlignViewport av;
private AlignmentPanel ap;
- //
- private boolean resizing = false;
-
- // This is set true if the user resizes whilst
- // the overview is being calculated
- private boolean resizeAgain = false;
+ private JCheckBoxMenuItem displayToggle;
- // Can set different properties in this seqCanvas than
- // main visible SeqCanvas
- private SequenceRenderer sr;
-
- jalview.renderer.seqfeatures.FeatureRenderer fr;
+ private boolean showHidden = true;
/**
* Creates a new OverviewPanel object.
{
this.av = alPanel.av;
this.ap = alPanel;
- setLayout(null);
-
- sr = new SequenceRenderer(av);
- sr.renderGaps = false;
- sr.forOverview = true;
- fr = new FeatureRenderer(ap);
- od = new OverviewDimensions(av.getRanges(),
+ od = new OverviewDimensionsShowHidden(av.getRanges(),
(av.isShowAnnotation() && av
.getAlignmentConservationAnnotation() != null));
+ oviewCanvas = new OverviewCanvas(od, av);
+ setLayout(new BorderLayout());
+ add(oviewCanvas, BorderLayout.CENTER);
+
addComponentListener(new ComponentAdapter()
{
@Override
@Override
public void mouseDragged(MouseEvent evt)
{
- if (!av.getWrapAlignment())
+ if (!SwingUtilities.isRightMouseButton(evt)
+ && !av.getWrapAlignment())
{
od.updateViewportFromMouse(evt.getX(), evt.getY(), av
- .getAlignment().getHiddenSequences(), av
- .getColumnSelection(), av.getRanges());
+ .getAlignment().getHiddenSequences(), av.getAlignment()
+ .getHiddenColumns());
ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
}
}
@Override
public void mousePressed(MouseEvent evt)
{
- if (!av.getWrapAlignment())
+ if (SwingUtilities.isRightMouseButton(evt))
+ {
+ if (!Platform.isAMac())
+ {
+ showPopupMenu(evt);
+ }
+ }
+ else if (!av.getWrapAlignment())
{
od.updateViewportFromMouse(evt.getX(), evt.getY(), av
- .getAlignment().getHiddenSequences(), av
- .getColumnSelection(), av.getRanges());
+ .getAlignment().getHiddenSequences(), av.getAlignment()
+ .getHiddenColumns());
ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
}
}
+
+ @Override
+ public void mouseClicked(MouseEvent evt)
+ {
+ if (SwingUtilities.isRightMouseButton(evt))
+ {
+ showPopupMenu(evt);
+ }
+ }
});
+
updateOverviewImage();
}
- /**
- * Updates the overview image when the related alignment panel is updated
+ /*
+ * Displays the popup menu and acts on user input
*/
- public void updateOverviewImage()
- {
- if (resizing)
- {
- resizeAgain = true;
- return;
- }
-
- resizing = true;
-
- if ((getWidth() > 0) && (getHeight() > 0))
- {
- od.setWidth(getWidth());
- od.setHeight(getHeight());
- }
-
- setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
-
- Thread thread = new Thread(this);
- thread.start();
- repaint();
- }
-
- @Override
- public void run()
+ private void showPopupMenu(MouseEvent e)
{
- miniMe = null;
-
- if (av.isShowSequenceFeatures())
- {
- fr.transferSettings(ap.getSeqPanel().seqCanvas.getFeatureRenderer());
- }
-
- // why do we need to set preferred size again? was set in
- // updateOverviewImage
- setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
-
- miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
- BufferedImage.TYPE_INT_RGB);
-
- Graphics mg = miniMe.getGraphics();
- mg.setColor(Color.orange);
- mg.fillRect(0, 0, od.getWidth(), miniMe.getHeight());
-
- // calculate sampleCol and sampleRow
- // alignment width is max number of residues/bases
- // alignment height is number of sequences
- int alwidth = av.getAlignment().getWidth();
- int alheight = av.getAlignment().getAbsoluteHeight();
-
- // sampleCol or sampleRow is the width/height allocated to each residue
- // in particular, sometimes we may need more than one row/col of the
- // BufferedImage allocated
- // sampleCol is how much of a residue to assign to each pixel
- // sampleRow is how many sequences to assign to each pixel
- float sampleCol = alwidth / (float) od.getWidth();
- float sampleRow = alheight / (float) od.getSequencesHeight();
-
- buildImage(sampleRow, sampleCol);
-
- // check for conservation annotation to make sure overview works for DNA too
- if (av.isShowAnnotation()
- && (av.getAlignmentConservationAnnotation() != null))
+ JPopupMenu popup = new JPopupMenu();
+ ActionListener menuListener = new ActionListener()
{
- renderer.updateFromAlignViewport(av);
- for (int col = 0; col < od.getWidth() && !resizeAgain; col++)
+ @Override
+ public void actionPerformed(ActionEvent event)
{
- mg.translate(col, od.getSequencesHeight());
- renderer.drawGraph(mg, av.getAlignmentConservationAnnotation(),
- av.getAlignmentConservationAnnotation().annotations,
- (int) (sampleCol) + 1, od.getGraphHeight(),
- (int) (col * sampleCol), (int) (col * sampleCol) + 1);
- mg.translate(-col, -od.getSequencesHeight());
-
+ // switch on/off the hidden columns view
+ toggleHiddenColumns();
+ displayToggle.setSelected(showHidden);
}
- }
- System.gc();
-
- resizing = false;
-
- if (resizeAgain)
- {
- resizeAgain = false;
- updateOverviewImage();
- }
- else
- {
- lastMiniMe = miniMe;
- }
-
- setBoxPosition();
+ };
+ displayToggle = new JCheckBoxMenuItem(
+ MessageManager.getString("label.togglehidden"));
+ displayToggle.setEnabled(true);
+ displayToggle.setSelected(showHidden);
+ popup.add(displayToggle);
+ displayToggle.addActionListener(menuListener);
+ popup.show(this, e.getX(), e.getY());
}
/*
- * Build the overview panel image
+ * Toggle overview display between showing hidden columns and hiding hidden columns
*/
- private void buildImage(float sampleRow, float sampleCol)
+ private void toggleHiddenColumns()
{
- int lastcol = -1;
- int lastrow = -1;
- int rgbColour = Color.white.getRGB();
-
- SequenceI seq = null;
- FeatureColourFinder finder = new FeatureColourFinder(fr);
-
- final boolean hasHiddenCols = av.hasHiddenColumns();
- boolean hiddenRow = false;
- // get hidden row and hidden column map once at beginning.
- // clone featureRenderer settings to avoid race conditions... if state is
- // updated just need to refresh again
- for (int row = 0; row < od.getSequencesHeight() && !resizeAgain; row++)
+ if (showHidden)
{
- boolean doCopy = true;
- int currentrow = (int) (row * sampleRow);
- if (currentrow != lastrow)
- {
- doCopy = false;
-
- lastrow = currentrow;
-
- // get the sequence which would be at alignment index 'lastrow' if no
- // rows were hidden, and determine whether it is hidden or not
- hiddenRow = av.getAlignment().isHidden(lastrow);
- seq = av.getAlignment().getSequenceAtAbsoluteIndex(lastrow);
- }
-
- for (int col = 0; col < od.getWidth() && !resizeAgain; col++)
- {
- if (doCopy)
- {
- rgbColour = miniMe.getRGB(col, row - 1);
- }
- else if ((int) (col * sampleCol) != lastcol
- || (int) (row * sampleRow) != lastrow)
- {
- lastcol = (int) (col * sampleCol);
- rgbColour = getColumnColourFromSequence(seq, hiddenRow,
- hasHiddenCols, lastcol, finder);
- }
- // else we just use the color we already have , so don't need to set it
-
- miniMe.setRGB(col, row, rgbColour);
- }
+ showHidden = false;
+ od = new OverviewDimensionsHideHidden(av.getRanges(),
+ (av.isShowAnnotation() && av
+ .getAlignmentConservationAnnotation() != null));
+ }
+ else
+ {
+ showHidden = true;
+ od = new OverviewDimensionsShowHidden(av.getRanges(),
+ (av.isShowAnnotation() && av
+ .getAlignmentConservationAnnotation() != null));
}
+ oviewCanvas.resetOviewDims(od);
+ updateOverviewImage();
}
- /*
- * Find the colour of a sequence at a specified column position
+ /**
+ * Updates the overview image when the related alignment panel is updated
*/
- private int getColumnColourFromSequence(
- jalview.datamodel.SequenceI seq,
- boolean hiddenRow, boolean hasHiddenCols, int lastcol,
- FeatureColourFinder finder)
+ public void updateOverviewImage()
{
- Color color = Color.white;
-
- if ((seq != null) && (seq.getLength() > lastcol))
+ if ((getWidth() > 0) && (getHeight() > 0))
{
- color = sr.getResidueColour(seq, lastcol, finder);
+ od.setWidth(getWidth());
+ od.setHeight(getHeight());
}
+
+ setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
- if (hiddenRow
- || (hasHiddenCols && !av.getColumnSelection()
- .isVisible(lastcol)))
+ if (oviewCanvas.restartDraw())
{
- color = color.darker().darker();
+ return;
}
- return color.getRGB();
+ Thread thread = new Thread(this);
+ thread.start();
+ repaint();
+
+ }
+
+ @Override
+ public void run()
+ {
+ oviewCanvas.draw(av.isShowSequenceFeatures(),
+ (av.isShowAnnotation() && av
+ .getAlignmentConservationAnnotation() != null), ap
+ .getSeqPanel().seqCanvas.getFeatureRenderer());
+ setBoxPosition();
}
/**
*/
public void setBoxPosition()
{
- od.setBoxPosition(av.getAlignment()
- .getHiddenSequences(), av.getColumnSelection(), av.getRanges());
+ od.setBoxPosition(av.getAlignment().getHiddenSequences(), av
+ .getAlignment().getHiddenColumns());
repaint();
}
-
-
- @Override
- public void paintComponent(Graphics g)
- {
- if (resizing || resizeAgain)
- {
- if (lastMiniMe == null)
- {
- g.setColor(Color.white);
- g.fillRect(0, 0, getWidth(), getHeight());
- }
- else
- {
- g.drawImage(lastMiniMe, 0, 0, getWidth(), getHeight(), this);
- }
- g.setColor(TRANS_GREY);
- g.fillRect(0, 0, getWidth(), getHeight());
- }
- else if (lastMiniMe != null)
- {
- g.drawImage(lastMiniMe, 0, 0, this);
- if (lastMiniMe != miniMe)
- {
- g.setColor(TRANS_GREY);
- g.fillRect(0, 0, getWidth(), getHeight());
- }
- }
-
- g.setColor(Color.red);
- od.drawBox(g);
- }
}
*/
package jalview.gui;
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.analysis.scoremodels.SimilarityParams;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
-import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.SeqCigar;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceI;
import jalview.jbgui.GPCAPanel;
-import jalview.schemes.ResidueProperties;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
import jalview.viewmodel.PCAModel;
import java.awt.BorderLayout;
import java.awt.Color;
+import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
PCAModel pcaModel;
+ private static final int MIN_WIDTH = 470;
+
+ private static final int MIN_HEIGHT = 250;
+
int top = 0;
/**
- * Creates a new PCAPanel object.
+ * Creates a new PCAPanel object using default score model and parameters
*
- * @param av
- * DOCUMENT ME!
- * @param s
- * DOCUMENT ME!
+ * @param alignPanel
*/
- public PCAPanel(AlignmentPanel ap)
+ public PCAPanel(AlignmentPanel alignPanel)
+ {
+ this(alignPanel, ScoreModels.getInstance()
+ .getDefaultModel(!alignPanel.av.getAlignment().isNucleotide())
+ .getName(), SimilarityParams.SeqSpace);
+ }
+
+ /**
+ * Constructor given sequence data, a similarity (or distance) score model
+ * name, and score calculation parameters
+ *
+ * @param alignPanel
+ * @param modelName
+ * @param params
+ */
+ public PCAPanel(AlignmentPanel alignPanel, String modelName,
+ SimilarityParamsI params)
{
super();
- this.av = ap.av;
- this.ap = ap;
+ this.av = alignPanel.av;
+ this.ap = alignPanel;
+ boolean nucleotide = av.getAlignment().isNucleotide();
progressBar = new ProgressBar(statusPanel, statusBar);
- boolean sameLength = true;
+ addInternalFrameListener(new InternalFrameAdapter()
+ {
+ @Override
+ public void internalFrameClosed(InternalFrameEvent e)
+ {
+ close_actionPerformed();
+ }
+ });
+
boolean selected = av.getSelectionGroup() != null
&& av.getSelectionGroup().getSize() > 0;
AlignmentView seqstrings = av.getAlignmentView(selected);
- boolean nucleotide = av.getAlignment().isNucleotide();
SequenceI[] seqs;
if (!selected)
{
{
seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
}
- SeqCigar sq[] = seqstrings.getSequences();
- int length = sq[0].getWidth();
-
- for (int i = 0; i < seqs.length; i++)
- {
- if (sq[i].getWidth() != length)
- {
- sameLength = false;
- break;
- }
- }
- if (!sameLength)
- {
- JvOptionPane.showMessageDialog(Desktop.desktop,
- MessageManager.getString("label.pca_sequences_not_aligned"),
- MessageManager.getString("label.sequences_not_aligned"),
- JvOptionPane.WARNING_MESSAGE);
-
- return;
- }
-
- addInternalFrameListener(new InternalFrameAdapter()
- {
- @Override
- public void internalFrameClosed(InternalFrameEvent e)
- {
- close_actionPerformed();
- }
- });
-
- pcaModel = new PCAModel(seqstrings, seqs, nucleotide);
+ ScoreModelI scoreModel = ScoreModels.getInstance().getScoreModel(
+ modelName, ap);
+ pcaModel = new PCAModel(seqstrings, seqs, nucleotide, scoreModel,
+ params);
PaintRefresher.Register(this, av.getSequenceSetId());
- rc = new RotatableCanvas(ap);
+ rc = new RotatableCanvas(alignPanel);
this.getContentPane().add(rc, BorderLayout.CENTER);
Thread worker = new Thread(this);
worker.start();
pcaModel = null;
}
+ /**
+ * Repopulate the options and actions under the score model menu when it is
+ * selected. Options will depend on whether 'nucleotide' or 'peptide'
+ * modelling is selected (and also possibly on whether any additional score
+ * models have been added).
+ */
@Override
- protected void scoreMatrix_menuSelected()
+ protected void scoreModel_menuSelected()
{
- scoreMatrixMenu.removeAll();
- for (final String sm : ResidueProperties.scoreMatrices.keySet())
- {
- if (ResidueProperties.getScoreMatrix(sm) != null)
+ scoreModelMenu.removeAll();
+ for (final ScoreModelI sm : ScoreModels.getInstance().getModels())
+ {
+ final String name = sm.getName();
+ JCheckBoxMenuItem jm = new JCheckBoxMenuItem(name);
+
+ /*
+ * if the score model doesn't provide a description, try to look one
+ * up in the text bundle, falling back on its name
+ */
+ String tooltip = sm.getDescription();
+ if (tooltip == null)
{
- // create an entry for this score matrix for use in PCA
- JCheckBoxMenuItem jm = new JCheckBoxMenuItem();
- jm.setText(MessageManager.getStringOrReturn("label.score_model_",
- sm));
- jm.setSelected(pcaModel.getScore_matrix().equals(sm));
- if ((ResidueProperties.scoreMatrices.get(sm).isDNA() && ResidueProperties.scoreMatrices
- .get(sm).isProtein())
- || pcaModel.isNucleotide() == ResidueProperties.scoreMatrices
- .get(sm).isDNA())
+ tooltip = MessageManager.getStringOrReturn("label.score_model_",
+ name);
+ }
+ jm.setToolTipText(tooltip);
+ jm.setSelected(pcaModel.getScoreModelName().equals(name));
+ if ((pcaModel.isNucleotide() && sm.isDNA())
+ || (!pcaModel.isNucleotide() && sm.isProtein()))
+ {
+ jm.addActionListener(new ActionListener()
{
- final PCAPanel us = this;
- jm.addActionListener(new ActionListener()
+ @Override
+ public void actionPerformed(ActionEvent e)
{
- @Override
- public void actionPerformed(ActionEvent e)
+ if (!pcaModel.getScoreModelName().equals(name))
{
- if (!pcaModel.getScore_matrix().equals(sm))
- {
- pcaModel.setScore_matrix(sm);
- Thread worker = new Thread(us);
- worker.start();
- }
+ ScoreModelI sm2 = ScoreModels.getInstance().getScoreModel(
+ name, ap);
+ pcaModel.setScoreModel(sm2);
+ Thread worker = new Thread(PCAPanel.this);
+ worker.start();
}
- });
- scoreMatrixMenu.add(jm);
- }
+ }
+ });
+ scoreModelMenu.add(jm);
}
}
}
// rc.invalidate();
nuclSetting.setSelected(pcaModel.isNucleotide());
protSetting.setSelected(!pcaModel.isNucleotide());
- jvVersionSetting.setSelected(pcaModel.isJvCalcMode());
top = pcaModel.getTop();
} catch (OutOfMemoryError er)
addKeyListener(rc);
Desktop.addInternalFrame(this, MessageManager
.getString("label.principal_component_analysis"), 475, 450);
+ this.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
}
}
if (!pcaModel.isNucleotide())
{
pcaModel.setNucleotide(true);
- pcaModel.setScore_matrix("DNA");
+ pcaModel.setScoreModel(ScoreModels.getInstance().getDefaultModel(
+ false));
Thread worker = new Thread(this);
worker.start();
}
if (pcaModel.isNucleotide())
{
pcaModel.setNucleotide(false);
- pcaModel.setScore_matrix("BLOSUM62");
+ pcaModel.setScoreModel(ScoreModels.getInstance()
+ .getDefaultModel(true));
Thread worker = new Thread(this);
worker.start();
}
}
- @Override
- protected void jvVersionSetting_actionPerfomed(ActionEvent arg0)
- {
- pcaModel.setJvCalcMode(jvVersionSetting.isSelected());
- Thread worker = new Thread(this);
- worker.start();
- }
-
/**
* DOCUMENT ME!
*/
}
;
Object[] alAndColsel = pcaModel.getSeqtrings()
- .getAlignmentAndColumnSelection(gc);
+ .getAlignmentAndHiddenColumns(gc);
if (alAndColsel != null && alAndColsel[0] != null)
{
if (true)
{
// make a new frame!
- AlignFrame af = new AlignFrame(al,
- (ColumnSelection) alAndColsel[1], AlignFrame.DEFAULT_WIDTH,
+ AlignFrame af = new AlignFrame(al, (HiddenColumns) alAndColsel[1],
+ AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
// >>>This is a fix for the moment, until a better solution is
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.Annotation;
-import jalview.datamodel.ColumnSelection;
import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.ColourSchemes;
import jalview.schemes.PIDColourScheme;
-import jalview.schemes.ResidueColourScheme;
import jalview.util.GroupUrlLink;
import jalview.util.GroupUrlLink.UrlStringTooLongException;
import jalview.util.MessageManager;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
{
if (sequence != null)
{
- ColumnSelection cs = ap.av.getColumnSelection();
- if (cs == null)
+ /* ColumnSelection cs = ap.av.getColumnSelection();
+ if (cs == null)
+ {
+ cs = new ColumnSelection();
+ }
+ cs.hideInsertionsFor(sequence);
+ ap.av.setColumnSelection(cs);*/
+
+ HiddenColumns hidden = ap.av.getAlignment().getHiddenColumns();
+ if (hidden == null)
{
- cs = new ColumnSelection();
+ hidden = new HiddenColumns();
}
- cs.hideInsertionsFor(sequence);
- ap.av.setColumnSelection(cs);
+ hidden.hideInsertionsFor(sequence);
+ ap.av.getAlignment().setHiddenColumns(hidden);
}
refresh();
}
return;
}
- int rsize = 0, gSize = sg.getSize();
- SequenceI[] rseqs, seqs = new SequenceI[gSize];
- SequenceFeature[] tfeatures, features = new SequenceFeature[gSize];
+ List<SequenceI> seqs = new ArrayList<SequenceI>();
+ List<SequenceFeature> features = new ArrayList<SequenceFeature>();
+ /*
+ * assemble dataset sequences, and template new sequence features,
+ * for the amend features dialog
+ */
+ int gSize = sg.getSize();
for (int i = 0; i < gSize; i++)
{
int start = sg.getSequenceAt(i).findPosition(sg.getStartRes());
int end = sg.findEndRes(sg.getSequenceAt(i));
if (start <= end)
{
- seqs[rsize] = sg.getSequenceAt(i).getDatasetSequence();
- features[rsize] = new SequenceFeature(null, null, null, start, end,
- "Jalview");
- rsize++;
+ seqs.add(sg.getSequenceAt(i).getDatasetSequence());
+ features.add(new SequenceFeature(null, null, null, start, end, null));
}
}
- rseqs = new SequenceI[rsize];
- tfeatures = new SequenceFeature[rsize];
- System.arraycopy(seqs, 0, rseqs, 0, rsize);
- System.arraycopy(features, 0, tfeatures, 0, rsize);
- features = tfeatures;
- seqs = rseqs;
+
if (ap.getSeqPanel().seqCanvas.getFeatureRenderer().amendFeatures(seqs,
features, true, ap))
{
public void changeColour_actionPerformed(String colourSchemeName)
{
SequenceGroup sg = getGroup();
- if (ResidueColourScheme.USER_DEFINED.equals(colourSchemeName))
- {
- /*
- * open a panel to load or configure a user-defined colour scheme
- */
- new UserDefinedColours(ap, sg);
- }
- else
+ /*
+ * switch to the chosen colour scheme (or null for None)
+ */
+ ColourSchemeI colourScheme = ColourSchemes.getInstance()
+ .getColourScheme(colourSchemeName, sg,
+ ap.av.getHiddenRepSequences());
+ sg.setColourScheme(colourScheme);
+ if (colourScheme instanceof Blosum62ColourScheme
+ || colourScheme instanceof PIDColourScheme)
{
- /*
- * switch to the chosen colour scheme (or null for None)
- */
- ColourSchemeI colourScheme = ColourSchemes.getInstance().getColourScheme(
- colourSchemeName, sg, ap.av.getHiddenRepSequences());
- sg.setColourScheme(colourScheme);
- if (colourScheme instanceof Blosum62ColourScheme
- || colourScheme instanceof PIDColourScheme)
- {
- sg.cs.setConsensus(AAFrequency.calculate(
- sg.getSequences(ap.av.getHiddenRepSequences()),
- sg.getStartRes(), sg.getEndRes() + 1));
- }
+ sg.cs.setConsensus(AAFrequency.calculate(
+ sg.getSequences(ap.av.getHiddenRepSequences()),
+ sg.getStartRes(), sg.getEndRes() + 1));
}
refresh();
public static final String SHOW_AUTOCALC_ABOVE = "SHOW_AUTOCALC_ABOVE";
+ public static final String SHOW_OCCUPANCY = "SHOW_OCCUPANCY";
+
private static final int MIN_FONT_SIZE = 1;
private static final int MAX_FONT_SIZE = 30;
openoverv.setSelected(Cache.getDefault("SHOW_OVERVIEW", false));
showUnconserved
.setSelected(Cache.getDefault("SHOW_UNCONSERVED", false));
+ showOccupancy.setSelected(Cache.getDefault(SHOW_OCCUPANCY, false));
showGroupConsensus.setSelected(Cache.getDefault("SHOW_GROUP_CONSENSUS",
false));
showGroupConservation.setSelected(Cache.getDefault(
Boolean.toString(idItalics.isSelected()));
Cache.applicationProperties.setProperty("SHOW_UNCONSERVED",
Boolean.toString(showUnconserved.isSelected()));
+ Cache.applicationProperties.setProperty(SHOW_OCCUPANCY,
+ Boolean.toString(showOccupancy.isSelected()));
Cache.applicationProperties.setProperty("SHOW_GROUP_CONSENSUS",
Boolean.toString(showGroupConsensus.isSelected()));
Cache.applicationProperties.setProperty("SHOW_GROUP_CONSERVATION",
conservation.setEnabled(annotations.isSelected());
quality.setEnabled(annotations.isSelected());
identity.setEnabled(annotations.isSelected());
+ showOccupancy.setEnabled(annotations.isSelected());
showGroupConsensus.setEnabled(annotations.isSelected());
showGroupConservation.setEnabled(annotations.isSelected());
showConsensHistogram.setEnabled(annotations.isSelected()
package jalview.gui;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.renderer.ScaleRenderer;
if (av.hasHiddenColumns())
{
- x = av.getColumnSelection().adjustForHiddenColumns(x);
+ x = av.getAlignment().getHiddenColumns().adjustForHiddenColumns(x);
}
if (x >= av.getAlignment().getWidth())
});
pop.add(item);
- if (av.getColumnSelection().hasHiddenColumns())
+ if (av.getAlignment().getHiddenColumns().hasHiddenColumns())
{
item = new JMenuItem(MessageManager.getString("action.reveal_all"));
item.addActionListener(new ActionListener()
if (av.hasHiddenColumns())
{
- res = av.getColumnSelection().adjustForHiddenColumns(res);
+ res = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(res);
}
if (res >= av.getAlignment().getWidth())
{
mouseDragging = true;
ColumnSelection cs = av.getColumnSelection();
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
int res = (evt.getX() / av.getCharWidth())
+ av.getRanges().getStartRes();
res = Math.max(0, res);
- res = cs.adjustForHiddenColumns(res);
+ res = hidden.adjustForHiddenColumns(res);
res = Math.min(res, av.getAlignment().getWidth() - 1);
min = Math.min(res, min);
max = Math.max(res, max);
int res = (evt.getX() / av.getCharWidth())
+ av.getRanges().getStartRes();
- res = av.getColumnSelection().adjustForHiddenColumns(res);
+ res = av.getAlignment().getHiddenColumns().adjustForHiddenColumns(res);
- if (av.getColumnSelection().getHiddenColumns() != null)
+ if (av.getAlignment().getHiddenColumns().getHiddenRegions() != null)
{
- for (int[] region : av.getColumnSelection().getHiddenColumns())
+ for (int[] region : av.getAlignment().getHiddenColumns()
+ .getHiddenRegions())
{
if (res + 1 == region[0] || res - 1 == region[1])
{
// Fill the selected columns
ColumnSelection cs = av.getColumnSelection();
- int avCharWidth = av.getCharWidth(), avCharHeight = av.getCharHeight();
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ int avCharWidth = av.getCharWidth();
+ int avCharHeight = av.getCharHeight();
if (cs != null)
{
if (av.hasHiddenColumns())
{
- if (cs.isVisible(sel))
+ if (hidden.isVisible(sel))
{
- sel = cs.findColumnPosition(sel);
+ sel = hidden.findColumnPosition(sel);
}
else
{
// draw any hidden column markers
gg.setColor(Color.blue);
int res;
- if (av.getShowHiddenMarkers()
- && av.getColumnSelection().getHiddenColumns() != null)
+
+ if (av.getShowHiddenMarkers() && hidden.getHiddenRegions() != null)
{
- for (int i = 0; i < av.getColumnSelection().getHiddenColumns()
+ for (int i = 0; i < hidden.getHiddenRegions()
.size(); i++)
{
- res = av.getColumnSelection().findHiddenRegionPosition(i)
+ res = hidden.findHiddenRegionPosition(i)
- startx;
if (res < 0 || res > widthx)
package jalview.gui;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
if (av.hasHiddenColumns())
{
- startx = av.getColumnSelection().adjustForHiddenColumns(startx);
- endx = av.getColumnSelection().adjustForHiddenColumns(endx);
+ startx = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(startx);
+ endx = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(endx);
}
int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
// WEST SCALE
if (av.hasHiddenColumns())
{
- endx = av.getColumnSelection().adjustForHiddenColumns(endx);
+ endx = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(endx);
}
SequenceI seq;
if (av.hasHiddenColumns())
{
- maxwidth = av.getColumnSelection().findColumnPosition(maxwidth) - 1;
+ maxwidth = av.getAlignment().getHiddenColumns()
+ .findColumnPosition(maxwidth) - 1;
}
while ((ypos <= canvasHeight) && (startRes < maxwidth))
{
g.setColor(Color.blue);
int res;
- for (int i = 0; i < av.getColumnSelection().getHiddenColumns()
- .size(); i++)
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ for (int i = 0; i < hidden.getHiddenRegions().size(); i++)
{
- res = av.getColumnSelection().findHiddenRegionPosition(i)
- - startRes;
+ res = hidden.findHiddenRegionPosition(i) - startRes;
if (res < 0 || res > endx - startRes)
{
(int) clip.getBounds().getHeight());
}
- drawPanel(g, startRes, endx, 0, al.getHeight(), ypos);
+ drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
if (av.isShowAnnotation())
{
}
else
{
- List<int[]> regions = av.getColumnSelection().getHiddenColumns();
+ List<int[]> regions = av.getAlignment().getHiddenColumns()
+ .getHiddenRegions();
int screenY = 0;
int blockStart = startRes;
g1.drawLine((blockEnd - blockStart + 1) * charWidth - 1,
0 + offset, (blockEnd - blockStart + 1) * charWidth - 1,
- (endSeq - startSeq) * charHeight + offset);
+ (endSeq - startSeq + 1) * charHeight + offset);
}
g1.translate(-screenY * charWidth, 0);
import jalview.commands.EditCommand.Edit;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import javax.swing.JPanel;
* @param evt
* @return
*/
- int findRes(MouseEvent evt)
+ int findColumn(MouseEvent evt)
{
int res = 0;
int x = evt.getX();
if (av.hasHiddenColumns())
{
- res = av.getColumnSelection().adjustForHiddenColumns(res);
+ res = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(res);
}
return res;
{
seqCanvas.cursorX += dx;
seqCanvas.cursorY += dy;
+
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+
if (av.hasHiddenColumns()
- && !av.getColumnSelection().isVisible(seqCanvas.cursorX))
+ && !hidden.isVisible(seqCanvas.cursorX))
{
int original = seqCanvas.cursorX - dx;
int maxWidth = av.getAlignment().getWidth();
- while (!av.getColumnSelection().isVisible(seqCanvas.cursorX)
+ while (!hidden.isVisible(seqCanvas.cursorX)
&& seqCanvas.cursorX < maxWidth && seqCanvas.cursorX > 0)
{
seqCanvas.cursorX += dx;
}
if (seqCanvas.cursorX >= maxWidth
- || !av.getColumnSelection().isVisible(seqCanvas.cursorX))
+ || !hidden.isVisible(seqCanvas.cursorX))
{
seqCanvas.cursorX = original;
}
{
ap.scrollUp(true);
}
- while (seqCanvas.cursorY + 1 > av.getRanges().getEndSeq())
+ while (seqCanvas.cursorY > av.getRanges().getEndSeq())
{
ap.scrollUp(false);
}
if (!av.getWrapAlignment())
{
- while (seqCanvas.cursorX < av.getColumnSelection()
- .adjustForHiddenColumns(av.getRanges().getStartRes()))
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ while (seqCanvas.cursorX < hidden.adjustForHiddenColumns(av
+ .getRanges().getStartRes()))
{
if (!ap.scrollRight(false))
{
break;
}
}
- while (seqCanvas.cursorX > av.getColumnSelection()
- .adjustForHiddenColumns(av.getRanges().getEndRes()))
+ while (seqCanvas.cursorX > hidden.adjustForHiddenColumns(av
+ .getRanges().getEndRes()))
{
if (!ap.scrollRight(true))
{
}
int seq = findSeq(evt);
- int res = findRes(evt);
+ int res = findColumn(evt);
if (seq < 0 || res < 0)
{
mouseDragged(evt);
}
- int res = findRes(evt);
+ final int column = findColumn(evt);
int seq = findSeq(evt);
- int pos;
- if (res < 0 || seq < 0 || seq >= av.getAlignment().getHeight())
+ if (column < 0 || seq < 0 || seq >= av.getAlignment().getHeight())
{
return;
}
SequenceI sequence = av.getAlignment().getSequenceAt(seq);
- if (res >= sequence.getLength())
+ if (column >= sequence.getLength())
{
return;
}
- pos = setStatusMessage(sequence, res, seq);
+ /*
+ * set status bar message, returning residue position in sequence
+ */
+ final int pos = setStatusMessage(sequence, column, seq);
if (ssm != null && pos > -1)
{
- mouseOverSequence(sequence, res, pos);
+ mouseOverSequence(sequence, column, pos);
}
tooltipText.setLength(6); // Cuts the buffer back to <html>
{
for (int g = 0; g < groups.length; g++)
{
- if (groups[g].getStartRes() <= res && groups[g].getEndRes() >= res)
+ if (groups[g].getStartRes() <= column
+ && groups[g].getEndRes() >= column)
{
if (!groups[g].getName().startsWith("JTreeGroup")
&& !groups[g].getName().startsWith("JGroup"))
}
}
- // use aa to see if the mouse pointer is on a
if (av.isShowSequenceFeatures())
{
- int rpos;
List<SequenceFeature> features = ap.getFeatureRenderer()
- .findFeaturesAtRes(sequence.getDatasetSequence(),
- rpos = sequence.findPosition(res));
- seqARep.appendFeatures(tooltipText, rpos, features,
+ .findFeaturesAtRes(sequence.getDatasetSequence(), pos);
+ seqARep.appendFeatures(tooltipText, pos, features,
this.ap.getSeqPanel().seqCanvas.fr.getMinMax());
}
if (tooltipText.length() == 6) // <html>
// avcontroller or viewModel
/**
- * Set status message in alignment panel
+ * Sets the status message in alignment panel, showing the sequence number
+ * (index) and id, residue and residue position for the given sequence and
+ * column position. Returns the calculated residue position in the sequence.
*
* @param sequence
* aligned sequence object
- * @param res
+ * @param column
* alignment column
* @param seq
* index of sequence in alignment
* @return position of res in sequence
*/
- int setStatusMessage(SequenceI sequence, int res, int seq)
+ int setStatusMessage(SequenceI sequence, final int column, int seq)
{
StringBuilder text = new StringBuilder(32);
/*
* Try to translate the display character to residue name (null for gap).
*/
- final String displayChar = String.valueOf(sequence.getCharAt(res));
+ final String displayChar = String.valueOf(sequence.getCharAt(column));
if (av.getAlignment().isNucleotide())
{
residue = ResidueProperties.nucleotideName.get(displayChar);
}
int pos = -1;
+ pos = sequence.findPosition(column);
if (residue != null)
{
- pos = sequence.findPosition(res);
text.append(" (").append(Integer.toString(pos)).append(")");
}
ap.alignFrame.statusBar.setText(text.toString());
}
/**
- * DOCUMENT ME!
- *
- * @param evt
- * DOCUMENT ME!
+ * {@inheritDoc}
*/
@Override
public void mouseDragged(MouseEvent evt)
{
if (mouseWheelPressed)
{
+ boolean inSplitFrame = ap.av.getCodingComplement() != null;
+ boolean copyChanges = inSplitFrame && av.isProteinFontAsCdna();
+
int oldWidth = av.getCharWidth();
// Which is bigger, left-right or up-down?
if (Math.abs(evt.getY() - lastMousePress.getY()) > Math.abs(evt
.getX() - lastMousePress.getX()))
{
+ /*
+ * on drag up or down, decrement or increment font size
+ */
int fontSize = av.font.getSize();
+ boolean fontChanged = false;
if (evt.getY() < lastMousePress.getY())
{
+ fontChanged = true;
fontSize--;
}
else if (evt.getY() > lastMousePress.getY())
{
+ fontChanged = true;
fontSize++;
}
fontSize = 1;
}
- av.setFont(
- new Font(av.font.getName(), av.font.getStyle(), fontSize),
- true);
- av.setCharWidth(oldWidth);
- ap.fontChanged();
+ if (fontChanged)
+ {
+ Font newFont = new Font(av.font.getName(), av.font.getStyle(),
+ fontSize);
+ av.setFont(newFont, true);
+ av.setCharWidth(oldWidth);
+ ap.fontChanged();
+ if (copyChanges)
+ {
+ ap.av.getCodingComplement().setFont(newFont, true);
+ SplitFrame splitFrame = (SplitFrame) ap.alignFrame
+ .getSplitViewContainer();
+ splitFrame.adjustLayout();
+ splitFrame.repaint();
+ }
+ }
}
else
{
+ /*
+ * on drag left or right, decrement or increment character width
+ */
+ int newWidth = 0;
if (evt.getX() < lastMousePress.getX() && av.getCharWidth() > 1)
{
- av.setCharWidth(av.getCharWidth() - 1);
+ newWidth = av.getCharWidth() - 1;
+ av.setCharWidth(newWidth);
}
else if (evt.getX() > lastMousePress.getX())
{
- av.setCharWidth(av.getCharWidth() + 1);
+ newWidth = av.getCharWidth() + 1;
+ av.setCharWidth(newWidth);
+ }
+ if (newWidth > 0)
+ {
+ ap.paintAlignment(false);
+ if (copyChanges)
+ {
+ /*
+ * need to ensure newWidth is set on cdna, regardless of which
+ * panel the mouse drag happened in; protein will compute its
+ * character width as 1:1 or 3:1
+ */
+ av.getCodingComplement().setCharWidth(newWidth);
+ SplitFrame splitFrame = (SplitFrame) ap.alignFrame
+ .getSplitViewContainer();
+ splitFrame.adjustLayout();
+ splitFrame.repaint();
+ }
}
-
- ap.paintAlignment(false);
}
FontMetrics fm = getFontMetrics(av.getFont());
return;
}
- int res = findRes(evt);
+ int res = findColumn(evt);
if (res < 0)
{
if (av.hasHiddenColumns())
{
fixedColumns = true;
- int y1 = av.getColumnSelection().getHiddenBoundaryLeft(startres);
- int y2 = av.getColumnSelection().getHiddenBoundaryRight(startres);
+ int y1 = av.getAlignment().getHiddenColumns()
+ .getHiddenBoundaryLeft(startres);
+ int y2 = av.getAlignment().getHiddenColumns()
+ .getHiddenBoundaryRight(startres);
if ((insertGap && startres > y1 && lastres < y1)
|| (!insertGap && startres < y2 && lastres > y2))
{
if (sg.getSize() == av.getAlignment().getHeight())
{
- if ((av.hasHiddenColumns() && startres < av
- .getColumnSelection().getHiddenBoundaryRight(startres)))
+ if ((av.hasHiddenColumns() && startres < av.getAlignment()
+ .getHiddenColumns().getHiddenBoundaryRight(startres)))
{
endEditing();
return;
}
}
+ /**
+ * Handler for double-click on a position with one or more sequence features.
+ * Opens the Amend Features dialog to allow feature details to be amended, or
+ * the feature deleted.
+ */
@Override
public void mouseClicked(MouseEvent evt)
{
List<SequenceFeature> features = seqCanvas.getFeatureRenderer()
.findFeaturesAtRes(sequence.getDatasetSequence(),
- sequence.findPosition(findRes(evt)));
+ sequence.findPosition(findColumn(evt)));
- if (features != null && features.size() > 0)
+ if (!features.isEmpty())
{
+ /*
+ * highlight the first feature at the position on the alignment
+ */
SearchResultsI highlight = new SearchResults();
highlight.addResult(sequence, features.get(0).getBegin(), features
.get(0).getEnd());
seqCanvas.highlightSearchResults(highlight);
- }
- if (features != null && features.size() > 0)
- {
- seqCanvas.getFeatureRenderer().amendFeatures(
- new SequenceI[] { sequence },
- features.toArray(new SequenceFeature[features.size()]),
- false, ap);
+ /*
+ * open the Amend Features dialog; clear highlighting afterwards,
+ * whether changes were made or not
+ */
+ List<SequenceI> seqs = Collections.singletonList(sequence);
+ seqCanvas.getFeatureRenderer().amendFeatures(seqs, features, false,
+ ap);
seqCanvas.highlightSearchResults(null);
}
}
*/
public void doMousePressedDefineMode(MouseEvent evt)
{
- final int res = findRes(evt);
+ final int res = findColumn(evt);
final int seq = findSeq(evt);
oldSeq = seq;
needOverviewUpdate = false;
if (av.cursorMode)
{
- seqCanvas.cursorX = findRes(evt);
+ seqCanvas.cursorX = findColumn(evt);
seqCanvas.cursorY = findSeq(evt);
seqCanvas.repaint();
return;
*
* @param evt
* @param res
- * @param sequence
+ * @param sequences
*/
void showPopupMenu(MouseEvent evt)
{
- final int res = findRes(evt);
+ final int res = findColumn(evt);
final int seq = findSeq(evt);
SequenceI sequence = av.getAlignment().getSequenceAt(seq);
List<SequenceFeature> allFeatures = ap.getFeatureRenderer()
*/
public void doMouseDraggedDefineMode(MouseEvent evt)
{
- int res = findRes(evt);
+ int res = findColumn(evt);
int y = findSeq(evt);
if (wrappedBlock != startWrapBlock)
*/
@Override
public void selection(SequenceGroup seqsel, ColumnSelection colsel,
- SelectionSource source)
+ HiddenColumns hidden, SelectionSource source)
{
// TODO: fix this hack - source of messages is align viewport, but SeqPanel
// handles selection messages...
// shared between viewports.
boolean iSentTheSelection = (av == source || (source instanceof AlignViewport && ((AlignmentViewport) source)
.getSequenceSetId().equals(av.getSequenceSetId())));
- if (iSentTheSelection || !av.followSelection)
+
+ if (iSentTheSelection)
{
- return;
+ // respond to our own event by updating dependent dialogs
+ if (ap.getCalculationDialog() != null)
+ {
+ ap.getCalculationDialog().validateCalcTypes();
+ }
+
+ // process further ?
+ if (!av.followSelection)
+ {
+ return;
+ }
}
/*
* Check for selection in a view of which this one is a dna/protein
* complement.
*/
- if (selectionFromTranslation(seqsel, colsel, source))
+ if (selectionFromTranslation(seqsel, colsel, hidden, source))
{
return;
}
}
else
{
- av.getColumnSelection().setElementsFrom(colsel);
+ av.getColumnSelection().setElementsFrom(colsel,
+ av.getAlignment().getHiddenColumns());
}
}
av.isColSelChanged(true);
if (copycolsel
&& av.hasHiddenColumns()
- && (av.getColumnSelection() == null || av.getColumnSelection()
- .getHiddenColumns() == null))
+ && (av.getAlignment().getHiddenColumns() == null || av
+ .getAlignment().getHiddenColumns().getHiddenRegions() == null))
{
System.err.println("Bad things");
}
PaintRefresher.Refresh(this, av.getSequenceSetId());
// ap.paintAlignment(false);
}
+
+ // lastly, update dependent dialogs
+ if (ap.getCalculationDialog() != null)
+ {
+ ap.getCalculationDialog().validateCalcTypes();
+ }
+
}
/**
* @param source
*/
protected boolean selectionFromTranslation(SequenceGroup seqsel,
- ColumnSelection colsel, SelectionSource source)
+ ColumnSelection colsel, HiddenColumns hidden,
+ SelectionSource source)
{
if (!(source instanceof AlignViewportI))
{
/*
* Map column selection
*/
- ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, sourceAv,
- av);
+ // ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, sourceAv,
+ // av);
+ ColumnSelection cs = new ColumnSelection();
+ HiddenColumns hs = new HiddenColumns();
+ MappingUtils.mapColumnSelection(colsel, hidden, sourceAv, av, cs, hs);
av.setColumnSelection(cs);
+ av.getAlignment().setHiddenColumns(hs);
+
+ // lastly, update any dependent dialogs
+ if (ap.getCalculationDialog() != null)
+ {
+ ap.getCalculationDialog().validateCalcTypes();
+ }
PaintRefresher.Refresh(this, av.getSequenceSetId());
import javax.swing.JCheckBox;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
-import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
*/
package jalview.gui;
+import jalview.api.AlignViewportI;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.renderer.ResidueShaderI;
{
final static int CHAR_TO_UPPER = 'A' - 'a';
- AlignViewport av;
+ AlignViewportI av;
FontMetrics fm;
*
* @param viewport
*/
- public SequenceRenderer(AlignViewport viewport)
+ public SequenceRenderer(AlignViewportI viewport)
{
this.av = viewport;
}
*/
void getBoxColour(ResidueShaderI shader, SequenceI seq, int i)
{
- if (shader != null)
+ if (shader.getColourScheme() != null)
{
resBoxColour = shader.findColour(seq.getCharAt(i),
i, seq);
drawBoxes(seq, start, end, y1);
- if (av.validCharWidth)
+ if (av.isValidCharWidth())
{
drawText(seq, start, end, y1);
}
package jalview.gui;
import jalview.api.SplitContainerI;
-import jalview.api.ViewStyleI;
import jalview.datamodel.AlignmentI;
import jalview.jbgui.GAlignFrame;
import jalview.jbgui.GSplitFrame;
: (!bottomAlignment.isNucleotide() ? bottomViewport : null);
if (protein != null && cdna != null)
{
- ViewStyleI vs = protein.getViewStyle();
- int scale = vs.isScaleProteinAsCdna() ? 3 : 1;
- vs.setCharWidth(scale * cdna.getViewStyle().getCharWidth());
- protein.setViewStyle(vs);
+ int scale = protein.isScaleProteinAsCdna() ? 3 : 1;
+ protein.setCharWidth(scale * cdna.getViewStyle().getCharWidth());
}
}
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
-import javax.swing.JOptionPane;
import javax.swing.table.AbstractTableModel;
/**
if (haveData)
{
cmb_filterOption.addItem(new FilterOption("Best Quality",
- "overall_quality", VIEWS_FILTER));
+ "overall_quality", VIEWS_FILTER, false));
cmb_filterOption.addItem(new FilterOption("Best Resolution",
- "resolution", VIEWS_FILTER));
+ "resolution", VIEWS_FILTER, false));
cmb_filterOption.addItem(new FilterOption("Most Protein Chain",
- "number_of_protein_chains", VIEWS_FILTER));
+ "number_of_protein_chains", VIEWS_FILTER, false));
cmb_filterOption.addItem(new FilterOption("Most Bound Molecules",
- "number_of_bound_molecules", VIEWS_FILTER));
+ "number_of_bound_molecules", VIEWS_FILTER, false));
cmb_filterOption.addItem(new FilterOption("Most Polymer Residues",
- "number_of_polymer_residues", VIEWS_FILTER));
+ "number_of_polymer_residues", VIEWS_FILTER, true));
}
cmb_filterOption.addItem(new FilterOption("Enter PDB Id", "-",
- VIEWS_ENTER_ID));
+ VIEWS_ENTER_ID, false));
cmb_filterOption.addItem(new FilterOption("From File", "-",
- VIEWS_FROM_FILE));
- FilterOption cachedOption = new FilterOption("Cached PDB Entries", "-",
- VIEWS_LOCAL_PDB);
- cmb_filterOption.addItem(cachedOption);
+ VIEWS_FROM_FILE, false));
- if (/*!haveData &&*/cachedPDBExists)
+ if (cachedPDBExists)
{
+ FilterOption cachedOption = new FilterOption("Cached PDB Entries",
+ "-", VIEWS_LOCAL_PDB, false);
+ cmb_filterOption.addItem(cachedOption);
cmb_filterOption.setSelectedItem(cachedOption);
}
import jalview.bin.Cache;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.gui.StructureViewer.ViewerType;
try
{
AlignmentI[] als = new Alignment[_alignwith.size()];
- ColumnSelection[] alc = new ColumnSelection[_alignwith.size()];
+ HiddenColumns[] alc = new HiddenColumns[_alignwith.size()];
int[] alm = new int[_alignwith.size()];
int a = 0;
{
als[a] = ap.av.getAlignment();
alm[a] = -1;
- alc[a++] = ap.av.getColumnSelection();
+ alc[a++] = ap.av.getAlignment().getHiddenColumns();
}
reply = getBinding().superposeStructures(als, alm, alc);
if (reply != null)
package jalview.gui;
import jalview.analysis.Conservation;
-import jalview.analysis.NJTree;
+import jalview.analysis.TreeModel;
import jalview.api.AlignViewportI;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceGroup;
import java.awt.print.PrinterJob;
import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.List;
import java.util.Vector;
import javax.swing.JColorChooser;
/** DOCUMENT ME!! */
public static final String PLACEHOLDER = " * ";
- NJTree tree;
+ TreeModel tree;
JScrollPane scrollPane;
* @param tree
* DOCUMENT ME!
*/
- public void setTree(NJTree tree)
+ public void setTree(TreeModel tree)
{
this.tree = tree;
tree.findHeight(tree.getTopNode());
* DOCUMENT ME!
* @param chunk
* DOCUMENT ME!
- * @param scale
+ * @param wscale
* DOCUMENT ME!
* @param width
* DOCUMENT ME!
* DOCUMENT ME!
*/
public void drawNode(Graphics g, SequenceNode node, float chunk,
- float scale, int width, int offx, int offy)
+ double wscale, int width, int offx, int offy)
{
if (node == null)
{
if ((node.left() == null) && (node.right() == null))
{
// Drawing leaf node
- float height = node.height;
- float dist = node.dist;
+ double height = node.height;
+ double dist = node.dist;
- int xstart = (int) ((height - dist) * scale) + offx;
- int xend = (int) (height * scale) + offx;
+ int xstart = (int) ((height - dist) * wscale) + offx;
+ int xend = (int) (height * wscale) + offx;
int ypos = (int) (node.ycount * chunk) + offy;
}
else
{
- drawNode(g, (SequenceNode) node.left(), chunk, scale, width, offx,
+ drawNode(g, (SequenceNode) node.left(), chunk, wscale, width, offx,
offy);
- drawNode(g, (SequenceNode) node.right(), chunk, scale, width, offx,
+ drawNode(g, (SequenceNode) node.right(), chunk, wscale, width, offx,
offy);
- float height = node.height;
- float dist = node.dist;
+ double height = node.height;
+ double dist = node.dist;
- int xstart = (int) ((height - dist) * scale) + offx;
- int xend = (int) (height * scale) + offx;
+ int xstart = (int) ((height - dist) * wscale) + offx;
+ int xend = (int) (height * wscale) + offx;
int ypos = (int) (node.ycount * chunk) + offy;
g.setColor(node.color.darker());
Rectangle pos = new Rectangle(xend - 2, ypos - 2, 5, 5);
nodeHash.put(node, pos);
- g.drawLine((int) (height * scale) + offx, ystart,
- (int) (height * scale) + offx, yend);
+ g.drawLine((int) (height * wscale) + offx, ystart,
+ (int) (height * wscale) + offx, yend);
String nodeLabel = "";
SequenceNode top = tree.getTopNode();
- float wscale = (float) ((width * .8) - (offx * 2))
+ double wscale = ((width * .8) - (offx * 2))
/ tree.getMaxHeight();
if (top.count == 0)
* DOCUMENT ME!
* @param chunk
* DOCUMENT ME!
- * @param scale
+ * @param wscale
* DOCUMENT ME!
* @param width
* DOCUMENT ME!
* DOCUMENT ME!
*/
public void pickNode(Rectangle pickBox, SequenceNode node, float chunk,
- float scale, int width, int offx, int offy)
+ double wscale, int width, int offx, int offy)
{
if (node == null)
{
if ((node.left() == null) && (node.right() == null))
{
- float height = node.height;
- float dist = node.dist;
+ double height = node.height;
+ double dist = node.dist;
- int xstart = (int) ((height - dist) * scale) + offx;
- int xend = (int) (height * scale) + offx;
+ int xstart = (int) ((height - dist) * wscale) + offx;
+ int xend = (int) (height * wscale) + offx;
int ypos = (int) (node.ycount * chunk) + offy;
}
else
{
- pickNode(pickBox, (SequenceNode) node.left(), chunk, scale, width,
+ pickNode(pickBox, (SequenceNode) node.left(), chunk, wscale, width,
offx, offy);
- pickNode(pickBox, (SequenceNode) node.right(), chunk, scale, width,
+ pickNode(pickBox, (SequenceNode) node.right(), chunk, wscale, width,
offx, offy);
}
}
labelLength = fm.stringWidth(longestName) + 20; // 20 allows for scrollbar
- float wscale = (width - labelLength - (offx * 2)) / tree.getMaxHeight();
+ double wscale = (width - labelLength - (offx * 2))
+ / tree.getMaxHeight();
SequenceNode top = tree.getTopNode();
threshold = (float) (x - offx)
/ (float) (getWidth() - labelLength - (2 * offx));
- tree.getGroups().removeAllElements();
- tree.groupNodes(tree.getTopNode(), threshold);
+ List<SequenceNode> groups = tree.groupNodes(threshold);
setColor(tree.getTopNode(), Color.black);
AlignmentPanel[] aps = getAssociatedPanels();
aps[a].av.getCodingComplement().clearSequenceColours();
}
}
- colourGroups();
+ colourGroups(groups);
}
PaintRefresher.Refresh(tp, ap.av.getSequenceSetId());
}
- void colourGroups()
+ void colourGroups(List<SequenceNode> groups)
{
AlignmentPanel[] aps = getAssociatedPanels();
- for (int i = 0; i < tree.getGroups().size(); i++)
+ for (int i = 0; i < groups.size(); i++)
{
Color col = new Color((int) (Math.random() * 255),
(int) (Math.random() * 255), (int) (Math.random() * 255));
- setColor(tree.getGroups().elementAt(i), col.brighter());
+ setColor(groups.get(i), col.brighter());
- Vector<SequenceNode> l = tree.findLeaves(tree.getGroups()
- .elementAt(i));
+ Vector<SequenceNode> l = tree.findLeaves(groups.get(i));
Vector<SequenceI> sequences = new Vector<SequenceI>();
package jalview.gui;
import jalview.analysis.AlignmentSorter;
+import jalview.analysis.AverageDistanceTree;
import jalview.analysis.NJTree;
+import jalview.analysis.TreeBuilder;
+import jalview.analysis.TreeModel;
+import jalview.analysis.scoremodels.ScoreModels;
import jalview.api.analysis.ScoreModelI;
-import jalview.api.analysis.ViewBasedAnalysisI;
+import jalview.api.analysis.SimilarityParamsI;
import jalview.bin.Cache;
import jalview.commands.CommandI;
import jalview.commands.OrderCommand;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
import jalview.datamodel.BinaryNode;
-import jalview.datamodel.ColumnSelection;
import jalview.datamodel.DBRefEntry;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.NodeTransformI;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.io.JalviewFileView;
import jalview.io.NewickFile;
import jalview.jbgui.GTreePanel;
-import jalview.schemes.ResidueProperties;
import jalview.util.ImageMaker;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
*/
public class TreePanel extends GTreePanel
{
- String type;
+ String treeType;
- String pwtype;
+ String scoreModelName; // if tree computed
+
+ String treeTitle; // if tree loaded
+
+ SimilarityParamsI similarityParams;
TreeCanvas treeCanvas;
- NJTree tree;
+ TreeModel tree;
AlignViewport av;
/**
* Creates a new TreePanel object.
*
- * @param av
- * DOCUMENT ME!
- * @param seqVector
- * DOCUMENT ME!
+ * @param ap
* @param type
- * DOCUMENT ME!
- * @param pwtype
- * DOCUMENT ME!
- * @param s
- * DOCUMENT ME!
- * @param e
- * DOCUMENT ME!
+ * @param modelName
+ * @param options
*/
- public TreePanel(AlignmentPanel ap, String type, String pwtype)
+ public TreePanel(AlignmentPanel ap, String type, String modelName,
+ SimilarityParamsI options)
{
super();
- initTreePanel(ap, type, pwtype, null, null);
+ this.similarityParams = options;
+ initTreePanel(ap, type, modelName, null, null);
// We know this tree has distances. JBPNote TODO: prolly should add this as
// a userdefined default
// showDistances(true);
}
- /**
- * Creates a new TreePanel object.
- *
- * @param av
- * DOCUMENT ME!
- * @param seqVector
- * DOCUMENT ME!
- * @param newtree
- * DOCUMENT ME!
- * @param type
- * DOCUMENT ME!
- * @param pwtype
- * DOCUMENT ME!
- */
- public TreePanel(AlignmentPanel ap, String type, String pwtype,
- NewickFile newtree)
- {
- super();
- initTreePanel(ap, type, pwtype, newtree, null);
- }
-
- public TreePanel(AlignmentPanel av, String type, String pwtype,
- NewickFile newtree, AlignmentView inputData)
+ public TreePanel(AlignmentPanel alignPanel, NewickFile newtree,
+ String theTitle, AlignmentView inputData)
{
super();
- initTreePanel(av, type, pwtype, newtree, inputData);
+ this.treeTitle = theTitle;
+ initTreePanel(alignPanel, null, null, newtree, inputData);
}
public AlignmentI getAlignment()
return treeCanvas.av;
}
- void initTreePanel(AlignmentPanel ap, String type, String pwtype,
+ void initTreePanel(AlignmentPanel ap, String type, String modelName,
NewickFile newTree, AlignmentView inputData)
{
av = ap.av;
- this.type = type;
- this.pwtype = pwtype;
+ this.treeType = type;
+ this.scoreModelName = modelName;
treeCanvas = new TreeCanvas(this, ap, scrollPane);
scrollPane.setViewportView(treeCanvas);
.println("new alignment sequences vector value is null");
}
- tree.UpdatePlaceHolders((List<SequenceI>) evt.getNewValue());
+ tree.updatePlaceHolders((List<SequenceI>) evt.getNewValue());
treeCanvas.nameHash.clear(); // reset the mapping between canvas
// rectangles and leafnodes
repaint();
}
});
- TreeLoader tl = new TreeLoader(newTree);
- if (inputData != null)
- {
- tl.odata = inputData;
- }
+ TreeLoader tl = new TreeLoader(newTree, inputData);
tl.start();
}
class TreeLoader extends Thread
{
- NewickFile newtree;
+ private NewickFile newtree;
- jalview.datamodel.AlignmentView odata = null;
+ private AlignmentView odata = null;
- public TreeLoader(NewickFile newtree)
+ public TreeLoader(NewickFile newickFile, AlignmentView inputData)
{
- this.newtree = newtree;
- if (newtree != null)
+ this.newtree = newickFile;
+ this.odata = inputData;
+
+ if (newickFile != null)
{
// Must be outside run(), as Jalview2XML tries to
// update distance/bootstrap visibility at the same time
- showBootstrap(newtree.HasBootstrap());
- showDistances(newtree.HasDistances());
+ showBootstrap(newickFile.HasBootstrap());
+ showDistances(newickFile.HasDistances());
}
}
if (newtree != null)
{
- if (odata == null)
- {
- tree = new NJTree(av.getAlignment().getSequencesArray(), newtree);
- }
- else
+ tree = new TreeModel(av.getAlignment().getSequencesArray(), odata,
+ newtree);
+ if (tree.getOriginalData() == null)
{
- tree = new NJTree(av.getAlignment().getSequencesArray(), odata,
- newtree);
- }
- if (!tree.hasOriginalSequenceData())
- {
- allowOriginalSeqData(false);
+ originalSeqData.setVisible(false);
}
}
else
{
- int start, end;
- SequenceI[] seqs;
- boolean selview = av.getSelectionGroup() != null
- && av.getSelectionGroup().getSize() > 1;
- AlignmentView seqStrings = av.getAlignmentView(selview);
- if (!selview)
- {
- start = 0;
- end = av.getAlignment().getWidth();
- seqs = av.getAlignment().getSequencesArray();
- }
- else
- {
- start = av.getSelectionGroup().getStartRes();
- end = av.getSelectionGroup().getEndRes() + 1;
- seqs = av.getSelectionGroup().getSequencesInOrder(
- av.getAlignment());
- }
- 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);
- }
+ ScoreModelI sm = ScoreModels.getInstance().getScoreModel(
+ scoreModelName, treeCanvas.ap);
+ TreeBuilder njtree = treeType.equals(TreeBuilder.NEIGHBOUR_JOINING) ? new NJTree(
+ av, sm, similarityParams) : new AverageDistanceTree(av, sm,
+ similarityParams);
+ tree = new TreeModel(njtree);
showDistances(true);
}
treeCanvas.setMarkPlaceholders(b);
}
- private void allowOriginalSeqData(boolean b)
- {
- originalSeqData.setVisible(b);
- }
-
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
- public NJTree getTree()
+ public TreeModel getTree()
{
return tree;
}
{
CutAndPasteTransfer cap = new CutAndPasteTransfer();
- StringBuffer buffer = new StringBuffer();
+ String newTitle = getPanelTitle();
- if (type.equals("AV"))
- {
- buffer.append("Average distance tree using ");
- }
- else
- {
- buffer.append("Neighbour joining tree using ");
- }
-
- if (pwtype.equals("BL"))
- {
- buffer.append("BLOSUM62");
- }
- else
- {
- buffer.append("PID");
- }
-
- jalview.io.NewickFile fout = new jalview.io.NewickFile(
- tree.getTopNode());
+ NewickFile fout = new NewickFile(tree.getTopNode());
try
{
- cap.setText(fout.print(tree.isHasBootstrap(), tree.isHasDistances(),
- tree.isHasRootDistance()));
- Desktop.addInternalFrame(cap, buffer.toString(), 500, 100);
+ cap.setText(fout.print(tree.hasBootstrap(), tree.hasDistances(),
+ tree.hasRootDistance()));
+ Desktop.addInternalFrame(cap, newTitle, 500, 100);
} catch (OutOfMemoryError oom)
{
new OOMWarning("generating newick tree file", oom);
{
jalview.io.NewickFile fout = new jalview.io.NewickFile(
tree.getTopNode());
- String output = fout.print(tree.isHasBootstrap(),
- tree.isHasDistances(), tree.isHasRootDistance());
+ String output = fout.print(tree.hasBootstrap(),
+ tree.hasDistances(), tree.hasRootDistance());
java.io.PrintWriter out = new java.io.PrintWriter(
new java.io.FileWriter(choice));
out.println(output);
@Override
public void originalSeqData_actionPerformed(ActionEvent e)
{
- if (!tree.hasOriginalSequenceData())
+ AlignmentView originalData = tree.getOriginalData();
+ if (originalData == null)
{
jalview.bin.Cache.log
.info("Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
} catch (Exception ex)
{
}
- ;
- Object[] alAndColsel = tree.seqData.getAlignmentAndColumnSelection(gc);
+
+ Object[] alAndColsel = originalData.getAlignmentAndHiddenColumns(gc);
if (alAndColsel != null && alAndColsel[0] != null)
{
if (true)
{
// make a new frame!
- AlignFrame af = new AlignFrame(al,
- (ColumnSelection) alAndColsel[1], AlignFrame.DEFAULT_WIDTH,
+ AlignFrame af = new AlignFrame(al, (HiddenColumns) alAndColsel[1],
+ AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
// >>>This is a fix for the moment, until a better solution is
public CommandI sortAlignmentIn(AlignmentPanel ap)
{
- AlignmentViewport av = ap.av;
- SequenceI[] oldOrder = av.getAlignment().getSequencesArray();
- AlignmentSorter.sortByTree(av.getAlignment(), tree);
+ AlignmentViewport viewport = ap.av;
+ SequenceI[] oldOrder = viewport.getAlignment().getSequencesArray();
+ AlignmentSorter.sortByTree(viewport.getAlignment(), tree);
CommandI undo;
- undo = new OrderCommand("Tree Sort", oldOrder, av.getAlignment());
+ undo = new OrderCommand("Tree Sort", oldOrder, viewport.getAlignment());
ap.paintAlignment(true);
return undo;
return treeCanvas.font;
}
- public void setTreeFont(Font font)
+ public void setTreeFont(Font f)
{
if (treeCanvas != null)
{
- treeCanvas.setFont(font);
+ treeCanvas.setFont(f);
}
}
}
if (newname != null)
{
- String oldname = ((SequenceNode) node).getName();
- // TODO : save in the undo object for this modification.
+ // String oldname = ((SequenceNode) node).getName();
+ // TODO : save oldname in the undo object for this modification.
((SequenceNode) node).setName(newname);
}
}
}
});
}
+
+ /**
+ * Formats a localised title for the tree panel, like
+ * <p>
+ * Neighbour Joining Using BLOSUM62
+ * <p>
+ * For a tree loaded from file, just uses the file name
+ * @return
+ */
+ public String getPanelTitle()
+ {
+ if (treeTitle != null)
+ {
+ return treeTitle;
+ }
+
+ /*
+ * i18n description of Neighbour Joining or Average Distance method
+ */
+ String treecalcnm = MessageManager.getString("label.tree_calc_"
+ + treeType.toLowerCase());
+
+ /*
+ * short score model name (long description can be too long)
+ */
+ String smn = scoreModelName;
+
+ /*
+ * put them together as <method> Using <model>
+ */
+ final String ttl = MessageManager.formatMessage("label.treecalc_title",
+ treecalcnm, smn);
+ return ttl;
+ }
}
*/
package jalview.gui;
-import jalview.api.structures.JalviewStructureDisplayI;
import jalview.bin.Cache;
-import jalview.datamodel.SequenceGroup;
import jalview.io.JalviewFileChooser;
import jalview.io.JalviewFileView;
import jalview.jbgui.GUserDefinedColours;
import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;
-import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
AlignmentPanel ap;
- SequenceGroup seqGroup;
-
- List<JButton> selectedButtons;
-
+ /*
+ * the colour scheme when the dialog was opened, or
+ * the scheme last saved to file
+ */
ColourSchemeI oldColourScheme;
- JInternalFrame frame;
+ /*
+ * flag is true if the colour scheme has been changed since the
+ * dialog was opened, or the changes last saved to file
+ */
+ boolean changed;
- JalviewStructureDisplayI structureViewer;
+ JInternalFrame frame;
List<JButton> upperCaseButtons;
List<JButton> lowerCaseButtons;
/**
- * Creates a new UserDefinedColours object.
+ * Creates and displays a new UserDefinedColours panel
*
- * @param ap
- * @param sg
+ * @param alignPanel
*/
- public UserDefinedColours(AlignmentPanel ap, SequenceGroup sg)
+ public UserDefinedColours(AlignmentPanel alignPanel)
{
this();
lcaseColour.setEnabled(false);
- this.ap = ap;
- seqGroup = sg;
+ this.ap = alignPanel;
- if (seqGroup != null)
- {
- oldColourScheme = seqGroup.getColourScheme();
- }
- else
- {
- oldColourScheme = ap.av.getGlobalColourScheme();
- }
+ oldColourScheme = alignPanel.av.getGlobalColourScheme();
if (oldColourScheme instanceof UserColourScheme)
{
showFrame();
}
- public UserDefinedColours(JalviewStructureDisplayI viewer,
- ColourSchemeI oldcs)
- {
- this();
- this.structureViewer = viewer;
-
- colorChooser.getSelectionModel().addChangeListener(this);
-
- oldColourScheme = oldcs;
-
- if (oldColourScheme instanceof UserColourScheme)
- {
- schemeName.setText(((UserColourScheme) oldColourScheme)
- .getSchemeName());
- }
-
- resetButtonPanel(false);
-
- showFrame();
-
- }
-
- public UserDefinedColours()
+ UserDefinedColours()
{
super();
selectedButtons = new ArrayList<JButton>();
Desktop.addInternalFrame(frame,
MessageManager.getString("label.user_defined_colours"),
MY_FRAME_WIDTH, MY_FRAME_HEIGHT, true);
-
- if (seqGroup != null)
- {
- frame.setTitle(frame.getTitle() + " (" + seqGroup.getName() + ")");
- }
}
/**
button.setBackground(newColour);
button.setForeground(ColorUtils.brighterThan(newColour));
}
+
+ changed = true;
}
/**
}
else
{
+ /*
+ * OK is treated as 'apply colours and close'
+ */
applyButton_actionPerformed();
+ /*
+ * If editing a named colour scheme, warn if changes
+ * have not been saved
+ */
+ warnIfUnsavedChanges();
+
try
{
frame.setClosed(true);
}
/**
+ * If we have made changes to an existing user defined colour scheme but not
+ * saved them, show a dialog with the option to save. If the user chooses to
+ * save, do so, else clear the colour scheme name to indicate a new colour
+ * scheme.
+ */
+ protected void warnIfUnsavedChanges()
+ {
+ if (!changed)
+ {
+ return;
+ }
+
+ String name = schemeName.getText().trim();
+ if (oldColourScheme != null && !"".equals(name)
+ && name.equals(oldColourScheme.getSchemeName()))
+ {
+ String message = MessageManager.formatMessage("label.scheme_changed",
+ name);
+ String title = MessageManager.getString("label.save_changes");
+ String[] options = new String[] { title,
+ MessageManager.getString("label.dont_save_changes"), };
+ final String question = JvSwingUtils.wrapTooltip(true, message);
+ int response = JvOptionPane.showOptionDialog(Desktop.desktop,
+ question, title, JvOptionPane.DEFAULT_OPTION,
+ JvOptionPane.PLAIN_MESSAGE, null, options, options[0]);
+
+ boolean saved = false;
+ if (response == 0)
+ {
+ /*
+ * prompt to save changes to file
+ */
+ saved = savebutton_actionPerformed();
+ }
+
+ /*
+ * if user chooses not to save (either in this dialog or in the
+ * save as dialogs), treat this as a new user defined colour scheme
+ */
+ if (!saved)
+ {
+ /*
+ * clear scheme name and re-apply as an anonymous scheme
+ */
+ schemeName.setText("");
+ applyButton_actionPerformed();
+ }
+ }
+ }
+
+ /**
* Returns true if the user has not made any colour selection (including if
* 'case-sensitive' selected and no lower-case colour chosen).
*
}
/**
- * Applies the current colour scheme to the alignment, sequence group or
- * structure view.
+ * Applies the current colour scheme to the alignment or sequence group
*/
@Override
protected void applyButton_actionPerformed()
}
UserColourScheme ucs = getSchemeFromButtons();
- if (seqGroup != null)
- {
- seqGroup.setColourScheme(ucs);
- ap.paintAlignment(true);
- }
- else if (ap != null)
- {
- ap.alignFrame.changeColour(ucs);
- }
- else if (structureViewer != null)
- {
- structureViewer.setJalviewColourScheme(ucs);
- }
+ ap.alignFrame.changeColour(ucs);
}
+ /**
+ * Constructs an instance of UserColourScheme with the residue colours
+ * currently set on the buttons on the panel
+ *
+ * @return
+ */
UserColourScheme getSchemeFromButtons()
{
}
/**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
+ * Action on clicking Load scheme button.
+ * <ul>
+ * <li>Open a file chooser to browse for files with extension .jc</li>
+ * <li>Load in the colour scheme and transfer it to this panel's buttons</li>
+ * <li>Register the loaded colour scheme</li>
+ * </ul>
*/
@Override
- protected void loadbutton_actionPerformed(ActionEvent e)
+ protected void loadbutton_actionPerformed()
{
upperCaseButtons = new ArrayList<JButton>();
lowerCaseButtons = new ArrayList<JButton>();
}
/**
- * DOCUMENT ME!
+ * Action on pressing the Save button.
+ * <ul>
+ * <li>Check a name has been entered</li>
+ * <li>Warn if the name already exists, remove any existing scheme of the same
+ * name if overwriting</li>
+ * <li>Do the standard file chooser thing to write with extension .jc</li>
+ * <li>If saving changes (possibly not yet applied) to the currently selected
+ * colour scheme, then apply the changes, as it is too late to back out now</li>
+ * <li>Don't apply the changes if the currently selected scheme is different,
+ * to allow a new scheme to be configured and saved but not applied</li>
+ * </ul>
+ * Returns true if the scheme is saved to file, false if it is not
*
- * @param e
- * DOCUMENT ME!
+ * @return
*/
@Override
- protected void savebutton_actionPerformed(ActionEvent e)
+ protected boolean savebutton_actionPerformed()
{
String name = schemeName.getText().trim();
if (name.length() < 1)
.getString("label.user_colour_scheme_must_have_name"),
MessageManager.getString("label.no_name_colour_scheme"),
JvOptionPane.WARNING_MESSAGE);
- return;
+ return false;
}
if (ColourSchemes.getInstance().nameExists(name))
JvOptionPane.YES_NO_OPTION);
if (reply != JvOptionPane.YES_OPTION)
{
- return;
+ return false;
}
- ColourSchemes.getInstance().removeColourScheme(name);
}
JalviewFileChooser chooser = new JalviewFileChooser("jc",
"Jalview User Colours");
int value = chooser.showSaveDialog(this);
- if (value == JalviewFileChooser.APPROVE_OPTION)
+ if (value != JalviewFileChooser.APPROVE_OPTION)
{
- File file = chooser.getSelectedFile();
- addNewColourScheme(file.getPath());
- saveToFile(file);
+ return false;
}
+
+ File file = chooser.getSelectedFile();
+ UserColourScheme updatedScheme = addNewColourScheme(file.getPath());
+ saveToFile(file);
+ changed = false;
+
+ /*
+ * changes saved - apply to alignment if we are changing
+ * the currently selected colour scheme; also make the updated
+ * colours the 'backout' scheme on Cancel
+ */
+ if (oldColourScheme != null
+ && name.equals(oldColourScheme.getSchemeName()))
+ {
+ oldColourScheme = updatedScheme;
+ applyButton_actionPerformed();
+ }
+ return true;
}
/**
* the colour scheme.
*
* @param filePath
+ * @return
*/
- protected void addNewColourScheme(String filePath)
+ protected UserColourScheme addNewColourScheme(String filePath)
{
/*
* update the delimited list of user defined colour files in
{
ap.alignFrame.buildColourMenu();
}
+
+ return ucs;
}
/**
* marshal to file
*/
JalviewUserColours ucs = new JalviewUserColours();
- ucs.setSchemeName(schemeName.getText());
+ String name = schemeName.getText();
+ ucs.setSchemeName(name);
try
{
PrintWriter out = new PrintWriter(new OutputStreamWriter(
}
/**
- * On cancel, restores the colour scheme before the dialogue was opened
- *
- * @param e
+ * On cancel, restores the colour scheme that was selected before the dialogue
+ * was opened
*/
@Override
- protected void cancelButton_actionPerformed(ActionEvent e)
+ protected void cancelButton_actionPerformed()
{
- if (ap != null)
- {
- if (seqGroup != null)
- {
- seqGroup.setColourScheme(oldColourScheme);
- }
- else
- {
- ap.alignFrame.changeColour(oldColourScheme);
- }
- ap.paintAlignment(true);
- }
-
- if (structureViewer != null)
- {
- structureViewer.setJalviewColourScheme(oldColourScheme);
- }
+ ap.alignFrame.changeColour(oldColourScheme);
+ ap.paintAlignment(true);
try
{
}
}
+ /**
+ * Action on selecting or deselecting the Case Sensitive option. When
+ * selected, separate buttons are shown for lower case residues, and the panel
+ * is resized to accommodate them. Also, the checkbox for 'apply colour to all
+ * lower case' is enabled.
+ */
@Override
- public void caseSensitive_actionPerformed(ActionEvent e)
+ public void caseSensitive_actionPerformed()
{
boolean selected = caseSensitive.isSelected();
resetButtonPanel(selected);
import jalview.bin.Cache;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.io.VamsasAppDatastore;
import java.util.Iterator;
import javax.swing.JInternalFrame;
-import javax.swing.JOptionPane;
import uk.ac.vamsas.client.ClientHandle;
import uk.ac.vamsas.client.IClient;
{
// TODO: rationalise : can only clear a selection over a
// referred to object
- ssm.sendSelection(null, null, me);
+ ssm.sendSelection(null, null, null, me);
return;
}
Class type = null;
}
if (send)
{
- ssm.sendSelection(jselection, colsel, me);
+ ssm.sendSelection(jselection, colsel, null, me);
}
// discard message.
for (int c = 0; c < jvobjs.length; c++)
@Override
public void selection(SequenceGroup seqsel,
- ColumnSelection colsel, SelectionSource source)
+ ColumnSelection colsel, HiddenColumns hidden,
+ SelectionSource source)
{
if (vobj2jv == null)
{
}
else
{
- int[] intervals = colsel.getVisibleContigs(
+ // int[] intervals = colsel.getVisibleContigs(
+ // seqsel.getStartRes(), seqsel.getEndRes() + 1);
+ int[] intervals = hidden.getVisibleContigs(
seqsel.getStartRes(), seqsel.getEndRes() + 1);
for (int iv = 0; iv < intervals.length; iv += 2)
{
import jalview.datamodel.Annotation;
import jalview.datamodel.ColumnSelection;
import jalview.datamodel.GraphLine;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.HiddenSequences;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
*/
public class ViewDef
{
- public String viewname;
+ // TODO this class is not used - remove?
+ public final String viewname;
- public HiddenSequences hidseqs;
+ public final HiddenSequences hidseqs;
- public ColumnSelection hiddencols;
+ public final HiddenColumns hiddencols;
- public Vector visibleGroups;
+ public final Hashtable hiddenRepSeqs;
- public Hashtable hiddenRepSeqs;
-
- public ViewDef(String viewname, HiddenSequences hidseqs,
- ColumnSelection hiddencols, Hashtable hiddenRepSeqs)
+ public ViewDef(String vname, HiddenSequences hseqs,
+ HiddenColumns hcols, Hashtable hRepSeqs)
{
- this.viewname = viewname;
- this.hidseqs = hidseqs;
- this.hiddencols = hiddencols;
- this.hiddenRepSeqs = hiddenRepSeqs;
+ this.viewname = vname;
+ this.hidseqs = hseqs;
+ this.hiddencols = hcols;
+ this.hiddenRepSeqs = hRepSeqs;
}
}
*/
public String printAnnotations(AlignmentAnnotation[] annotations,
List<SequenceGroup> list, Hashtable properties,
- ColumnSelection cs, AlignmentI al, ViewDef view)
+ HiddenColumns cs,
+ AlignmentI al, ViewDef view)
{
if (view != null)
{
}
if (list == null)
{
- list = view.visibleGroups;
+ // list = view.visibleGroups;
}
if (cs == null)
{
if (cs != null && cs.hasHiddenColumns())
{
text.append("VIEW_HIDECOLS\t");
- List<int[]> hc = cs.getHiddenColumns();
+ List<int[]> hc = cs.getHiddenRegions();
boolean comma = false;
for (int[] r : hc)
{
return false;
}
- public void printGroups(List<SequenceGroup> list)
+ protected void printGroups(List<SequenceGroup> list)
{
SequenceI seqrep = null;
for (SequenceGroup sg : list)
if (sg.cs != null)
{
text.append("colour=");
- text.append(sg.cs.toString());
+ text.append(ColourSchemeProperty.getColourName(sg.cs
+ .getColourScheme()));
text.append("\t");
if (sg.cs.getThreshold() != 0)
{
String file, DataSourceType protocol)
{
ColumnSelection colSel = viewport.getColumnSelection();
+ HiddenColumns hidden = viewport.getAlignment().getHiddenColumns();
if (colSel == null)
{
colSel = new ColumnSelection();
}
- boolean rslt = readAnnotationFile(viewport.getAlignment(), colSel,
+ if (hidden == null)
+ {
+ hidden = new HiddenColumns();
+ }
+ boolean rslt = readAnnotationFile(viewport.getAlignment(), hidden,
file, protocol);
- if (rslt && (colSel.hasSelectedColumns() || colSel.hasHiddenColumns()))
+ if (rslt && (colSel.hasSelectedColumns() || hidden.hasHiddenColumns()))
{
viewport.setColumnSelection(colSel);
+ viewport.getAlignment().setHiddenColumns(hidden);
}
return rslt;
return readAnnotationFile(al, null, file, sourceType);
}
- public boolean readAnnotationFile(AlignmentI al, ColumnSelection colSel,
+ public boolean readAnnotationFile(AlignmentI al, HiddenColumns hidden,
String file, DataSourceType sourceType)
{
BufferedReader in = null;
}
if (in != null)
{
- return parseAnnotationFrom(al, colSel, in);
+ return parseAnnotationFrom(al, hidden, in);
}
} catch (Exception ex)
private static String GRAPHLINE = "GRAPHLINE", COMBINE = "COMBINE";
- public boolean parseAnnotationFrom(AlignmentI al, ColumnSelection colSel,
+ public boolean parseAnnotationFrom(AlignmentI al, HiddenColumns hidden,
BufferedReader in) throws Exception
{
nlinesread = 0;
{
if (st.hasMoreTokens())
{
- if (colSel == null)
+ if (hidden == null)
{
- colSel = new ColumnSelection();
+ hidden = new HiddenColumns();
}
- parseHideCols(colSel, st.nextToken());
+ parseHideCols(hidden, st.nextToken());
}
modified = true;
continue;
}
if (sr != null)
{
- if (colSel == null)
+ if (hidden == null)
{
System.err
.println("Cannot process HIDE_INSERTIONS without an alignment view: Ignoring line: "
else
{
// consider deferring this till after the file has been parsed ?
- colSel.hideInsertionsFor(sr);
+ hidden.hideInsertionsFor(sr);
}
}
modified = true;
return modified;
}
- private void parseHideCols(ColumnSelection colSel, String nextToken)
+ private void parseHideCols(HiddenColumns hidden, String nextToken)
{
StringTokenizer inval = new StringTokenizer(nextToken, ",");
while (inval.hasMoreTokens())
from = to = Integer.parseInt(range);
if (from >= 0)
{
- colSel.hideColumns(from, to);
+ hidden.hideColumns(from, to);
}
}
else
}
if (from > 0 && to >= from)
{
- colSel.hideColumns(from, to);
+ hidden.hideColumns(from, to);
}
}
}
return printAnnotations(viewport.isShowAnnotation() ? viewport
.getAlignment().getAlignmentAnnotation() : null, viewport
.getAlignment().getGroups(), viewport.getAlignment()
- .getProperties(), viewport.getColumnSelection(),
+ .getProperties(), viewport.getAlignment().getHiddenColumns(),
viewport.getAlignment(), null);
}
return new FeaturesFile();
}
},
+ ScoreMatrix("Substitution matrix", "", false, false)
+ {
+ @Override
+ public AlignmentFileReaderI getReader(FileParse source)
+ throws IOException
+ {
+ return new ScoreMatrixFile(source);
+ }
+
+ @Override
+ public AlignmentFileWriterI getWriter(AlignmentI al)
+ {
+ return null;
+ }
+ },
PDB("PDB", "pdb,ent", true, false)
{
@Override
import jalview.bin.Cache;
import jalview.bin.Jalview;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
if (source instanceof ComplexAlignFile)
{
- ColumnSelection colSel = ((ComplexAlignFile) source)
- .getColumnSelection();
+ HiddenColumns colSel = ((ComplexAlignFile) source)
+ .getHiddenColumns();
SequenceI[] hiddenSeqs = ((ComplexAlignFile) source)
.getHiddenSequences();
String colourSchemeName = ((ComplexAlignFile) source)
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
}
public String formatSequences(FileFormatI format, AlignmentI alignment,
- String[] omitHidden, int[] exportRange, ColumnSelection colSel)
+ String[] omitHidden, int[] exportRange, HiddenColumns hidden)
{
return formatSequences(format, alignment, omitHidden, exportRange,
- getCacheSuffixDefault(format), colSel, null);
+ getCacheSuffixDefault(format), hidden, null);
}
/**
- * hack function to replace seuqences with visible sequence strings before
+ * hack function to replace sequences with visible sequence strings before
* generating a string of the alignment in the given format.
*
* @param format
*/
public String formatSequences(FileFormatI format, AlignmentI alignment,
String[] omitHidden, int[] exportRange, boolean suffix,
- ColumnSelection colSel)
+ HiddenColumns hidden)
{
return formatSequences(format, alignment, omitHidden, exportRange,
- suffix, colSel, null);
+ suffix, hidden, null);
}
public String formatSequences(FileFormatI format, AlignmentI alignment,
String[] omitHidden, int[] exportRange, boolean suffix,
- ColumnSelection colSel, SequenceGroup selgp)
+ HiddenColumns hidden, SequenceGroup selgp)
{
if (omitHidden != null)
{
AlignmentAnnotation na = new AlignmentAnnotation(ala[i]);
if (selgp != null)
{
- colSel.makeVisibleAnnotation(selgp.getStartRes(),
+ hidden.makeVisibleAnnotation(selgp.getStartRes(),
selgp.getEndRes(), na);
}
else
{
- colSel.makeVisibleAnnotation(na);
+ hidden.makeVisibleAnnotation(na);
}
alv.addAnnotation(na);
}
String bioJSON = new FormatAdapter(ap, exportData.getSettings())
.formatSequences(FileFormat.Json, exportData.getAlignment(),
exportData.getOmitHidden(), exportData
- .getStartEndPostions(), ap.getAlignViewport()
- .getColumnSelection());
+.getStartEndPostions(), ap.getAlignViewport()
+ .getAlignment().getHiddenColumns());
return bioJSON;
}
import jalview.api.ComplexAlignFile;
import jalview.api.FeatureSettingsModelI;
import jalview.api.FeaturesDisplayedI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceI;
import java.io.IOException;
private boolean showSeqFeatures;
- private ColumnSelection columnSelection;
+ private HiddenColumns hiddenColumns;
private SequenceI[] hiddenSequences;
this.showSeqFeatures = jsonFile.isShowSeqFeatures();
this.globalColourScheme = jsonFile.getGlobalColourScheme();
this.hiddenSequences = jsonFile.getHiddenSequences();
- this.columnSelection = jsonFile.getColumnSelection();
+ this.hiddenColumns = jsonFile.getHiddenColumns();
this.displayedFeatures = jsonFile.getDisplayedFeatures();
} catch (Exception e)
{
}
@Override
- public ColumnSelection getColumnSelection()
+ public HiddenColumns getHiddenColumns()
{
- return columnSelection;
+ return hiddenColumns;
}
- public void setColumnSelection(ColumnSelection columnSelection)
+ public void setHiddenColumns(HiddenColumns hidden)
{
- this.columnSelection = columnSelection;
+ this.hiddenColumns = hidden;
}
@Override
boolean lineswereskipped = false;
boolean isBinary = false; // true if length is non-zero and non-printable
// characters are encountered
+
try
{
if (!closeSource)
{
source.mark();
}
+ boolean aaIndexHeaderRead = false;
+
while ((data = source.nextLine()) != null)
{
bytesRead += data.length();
}
data = data.toUpperCase();
+ if (data.startsWith(ScoreMatrixFile.SCOREMATRIX))
+ {
+ reply = FileFormat.ScoreMatrix;
+ break;
+ }
+ if (data.startsWith("H ") && !aaIndexHeaderRead)
+ {
+ aaIndexHeaderRead = true;
+ }
+ if (data.startsWith("D ") && aaIndexHeaderRead)
+ {
+ reply = FileFormat.ScoreMatrix;
+ break;
+ }
if (data.startsWith("##GFF-VERSION"))
{
// GFF - possibly embedded in a Jalview features file!
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.Annotation;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.HiddenSequences;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
import jalview.json.binding.biojson.v1.SequenceGrpPojo;
import jalview.json.binding.biojson.v1.SequencePojo;
import jalview.renderer.seqfeatures.FeatureColourFinder;
+import jalview.schemes.ColourSchemeProperty;
import jalview.schemes.JalviewColourScheme;
import jalview.schemes.ResidueColourScheme;
import jalview.util.ColorUtils;
private FeatureRenderer fr;
- private List<int[]> hiddenColumns;
-
- private ColumnSelection columnSelection;
+ private HiddenColumns hiddenColumns;
private List<String> hiddenSeqRefs;
{
SequenceGrpPojo seqGrpPojo = new SequenceGrpPojo();
seqGrpPojo.setGroupName(seqGrp.getName());
- seqGrpPojo.setColourScheme(seqGrp.getColourScheme()
- .getSchemeName());
+ seqGrpPojo.setColourScheme(ColourSchemeProperty
+ .getColourName(seqGrp.getColourScheme()));
seqGrpPojo.setColourText(seqGrp.getColourText());
seqGrpPojo.setDescription(seqGrp.getDescription());
seqGrpPojo.setDisplayBoxes(seqGrp.getDisplayBoxes());
// hidden column business
if (getViewport().hasHiddenColumns())
{
- List<int[]> hiddenCols = getViewport().getColumnSelection()
- .getHiddenColumns();
+ List<int[]> hiddenCols = getViewport().getAlignment()
+ .getHiddenColumns()
+ .getHiddenRegions();
StringBuilder hiddenColsBuilder = new StringBuilder();
for (int[] range : hiddenCols)
{
String hiddenCols = (String) jvSettingsJson.get("hiddenCols");
if (hiddenCols != null && !hiddenCols.isEmpty())
{
- columnSelection = new ColumnSelection();
+ hiddenColumns = new HiddenColumns();
String[] rangeStrings = hiddenCols.split(";");
for (String rangeString : rangeStrings)
{
String[] range = rangeString.split("-");
- columnSelection.hideColumns(Integer.valueOf(range[0]),
+ hiddenColumns.hideColumns(Integer.valueOf(range[0]),
Integer.valueOf(range[1]));
}
}
}
}
}
- globalColourScheme = viewport.getGlobalColourScheme().getSchemeName();
+ globalColourScheme = ColourSchemeProperty.getColourName(viewport
+ .getGlobalColourScheme());
setDisplayedFeatures(viewport.getFeaturesDisplayed());
showSeqFeatures = viewport.isShowSequenceFeatures();
return annotations;
}
- public List<int[]> getHiddenColumns()
- {
- return hiddenColumns;
- }
-
@Override
- public ColumnSelection getColumnSelection()
+ public HiddenColumns getHiddenColumns()
{
- return columnSelection;
+ return hiddenColumns;
}
- public void setColumnSelection(ColumnSelection columnSelection)
+ public void setHiddenColumns(HiddenColumns hidden)
{
- this.columnSelection = columnSelection;
+ this.hiddenColumns = hidden;
}
@Override
--- /dev/null
+package jalview.io;
+
+import jalview.analysis.scoremodels.ScoreMatrix;
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.datamodel.SequenceI;
+
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+/**
+ * A class that can parse a file containing a substitution matrix and register
+ * it for use in Jalview
+ * <p>
+ * Accepts 'NCBI' format (e.g.
+ * https://www.ncbi.nlm.nih.gov/Class/FieldGuide/BLOSUM62.txt), with the
+ * addition of a header line to provide a matrix name, e.g.
+ *
+ * <pre>
+ * ScoreMatrix BLOSUM62
+ * </pre>
+ *
+ * Also accepts 'AAindex' format (as described at
+ * http://www.genome.jp/aaindex/aaindex_help.html) with the minimum data
+ * required being
+ *
+ * <pre>
+ * H accession number (used as score matrix identifier in Jalview)
+ * D description (used for tooltip in Jalview)
+ * M rows = symbolList
+ * and the substitution scores
+ * </pre>
+ */
+public class ScoreMatrixFile extends AlignFile implements
+ AlignmentFileReaderI
+{
+ // first non-comment line identifier - also checked in IdentifyFile
+ public static final String SCOREMATRIX = "SCOREMATRIX";
+
+ private static final String DELIMITERS = " ,\t";
+
+ private static final String COMMENT_CHAR = "#";
+
+ private String matrixName;
+
+ /*
+ * aaindex format has scores for diagonal and below only
+ */
+ boolean isLowerDiagonalOnly;
+
+ /*
+ * ncbi format has symbols as first column on score rows
+ */
+ boolean hasGuideColumn;
+
+ /**
+ * Constructor
+ *
+ * @param source
+ * @throws IOException
+ */
+ public ScoreMatrixFile(FileParse source) throws IOException
+ {
+ super(false, source);
+ }
+
+ @Override
+ public String print(SequenceI[] sqs, boolean jvsuffix)
+ {
+ return null;
+ }
+
+ /**
+ * Parses the score matrix file, and if successful registers the matrix so it
+ * will be shown in Jalview menus. This method is not thread-safe (a separate
+ * instance of this class should be used by each thread).
+ */
+ @Override
+ public void parse() throws IOException
+ {
+ ScoreMatrix sm = parseMatrix();
+
+ ScoreModels.getInstance().registerScoreModel(sm);
+ }
+
+ /**
+ * Parses the score matrix file and constructs a ScoreMatrix object. If an
+ * error is found in parsing, it is thrown as FileFormatException. Any
+ * warnings are written to syserr.
+ *
+ * @return
+ * @throws IOException
+ */
+ public ScoreMatrix parseMatrix() throws IOException
+ {
+ ScoreMatrix sm = null;
+ int lineNo = 0;
+ String name = null;
+ char[] alphabet = null;
+ float[][] scores = null;
+ int size = 0;
+ int row = 0;
+ String err = null;
+ String data;
+ isLowerDiagonalOnly = false;
+
+ while ((data = nextLine()) != null)
+ {
+ lineNo++;
+ data = data.trim();
+ if (data.startsWith(COMMENT_CHAR) || data.length() == 0)
+ {
+ continue;
+ }
+ if (data.toUpperCase().startsWith(SCOREMATRIX))
+ {
+ /*
+ * Parse name from ScoreMatrix <name>
+ * we allow any delimiter after ScoreMatrix then take the rest of the line
+ */
+ if (name != null)
+ {
+ throw new FileFormatException(
+ "Error: 'ScoreMatrix' repeated in file at line "
+ + lineNo);
+ }
+ StringTokenizer nameLine = new StringTokenizer(data, DELIMITERS);
+ if (nameLine.countTokens() < 2)
+ {
+ err = "Format error: expected 'ScoreMatrix <name>', found '"
+ + data + "' at line " + lineNo;
+ throw new FileFormatException(err);
+ }
+ nameLine.nextToken(); // 'ScoreMatrix'
+ name = nameLine.nextToken(); // next field
+ name = data.substring(1).substring(data.substring(1).indexOf(name));
+ continue;
+ }
+ else if (data.startsWith("H ") && name == null)
+ {
+ /*
+ * AAindex identifier
+ */
+ return parseAAIndexFormat(lineNo, data);
+ }
+ else if (name == null)
+ {
+ err = "Format error: 'ScoreMatrix <name>' should be the first non-comment line";
+ throw new FileFormatException(err);
+ }
+
+ /*
+ * next non-comment line after ScoreMatrix should be the
+ * column header line with the alphabet of scored symbols
+ */
+ if (alphabet == null)
+ {
+ StringTokenizer columnHeadings = new StringTokenizer(data,
+ DELIMITERS);
+ size = columnHeadings.countTokens();
+ alphabet = new char[size];
+ int col = 0;
+ while (columnHeadings.hasMoreTokens())
+ {
+ alphabet[col++] = columnHeadings.nextToken().charAt(0);
+ }
+ scores = new float[size][];
+ continue;
+ }
+
+ /*
+ * too much information
+ */
+ if (row >= size)
+ {
+ err = "Unexpected extra input line in score model file: '" + data
+ + "'";
+ throw new FileFormatException(err);
+ }
+
+ parseValues(data, lineNo, scores, row, alphabet);
+ row++;
+ }
+
+ /*
+ * out of data - check we found enough
+ */
+ if (row < size)
+ {
+ err = String
+ .format("Expected %d rows of score data in score matrix but only found %d",
+ size, row);
+ throw new FileFormatException(err);
+ }
+
+ /*
+ * If we get here, then name, alphabet and scores have been parsed successfully
+ */
+ sm = new ScoreMatrix(name, alphabet, scores);
+ matrixName = name;
+
+ return sm;
+ }
+
+ /**
+ * Parse input as AAIndex format, starting from the header line with the
+ * accession id
+ *
+ * @param lineNo
+ * @param data
+ * @return
+ * @throws IOException
+ */
+ protected ScoreMatrix parseAAIndexFormat(int lineNo, String data)
+ throws IOException
+ {
+ String name = data.substring(2).trim();
+ String description = null;
+
+ float[][] scores = null;
+ char[] alphabet = null;
+ int row = 0;
+ int size = 0;
+
+ while ((data = nextLine()) != null)
+ {
+ lineNo++;
+ data = data.trim();
+ if (skipAAindexLine(data))
+ {
+ continue;
+ }
+ if (data.startsWith("D "))
+ {
+ description = data.substring(2).trim();
+ }
+ else if (data.startsWith("M "))
+ {
+ alphabet = parseAAindexRowsColumns(lineNo, data);
+ size = alphabet.length;
+ scores = new float[size][size];
+ }
+ else if (scores == null)
+ {
+ throw new FileFormatException(
+ "No alphabet specified in matrix file");
+ }
+ else if (row >= size)
+ {
+ throw new FileFormatException("Too many data rows in matrix file");
+ }
+ else
+ {
+ parseValues(data, lineNo, scores, row, alphabet);
+ row++;
+ }
+ }
+
+ ScoreMatrix sm = new ScoreMatrix(name, description, alphabet, scores);
+ matrixName = name;
+
+ return sm;
+ }
+
+ /**
+ * Parse one row of score values, delimited by whitespace or commas. The line
+ * may optionally include the symbol from which the scores are defined. Values
+ * may be present for all columns, or only up to the diagonal (in which case
+ * upper diagonal values are set symmetrically).
+ *
+ * @param data
+ * the line to be parsed
+ * @param lineNo
+ * @param scores
+ * the score matrix to add data to
+ * @param row
+ * the row number / alphabet index position
+ * @param alphabet
+ * @return
+ * @throws exception
+ * if invalid, or too few, or too many values
+ */
+ protected void parseValues(String data, int lineNo, float[][] scores,
+ int row, char[] alphabet) throws FileFormatException
+ {
+ String err;
+ int size = alphabet.length;
+ StringTokenizer scoreLine = new StringTokenizer(data, DELIMITERS);
+
+ int tokenCount = scoreLine.countTokens();
+
+ /*
+ * inspect first row to see if it includes the symbol in the first column,
+ * and to see if it is lower diagonal values only (i.e. just one score)
+ */
+ if (row == 0)
+ {
+ if (data.startsWith(String.valueOf(alphabet[0])))
+ {
+ hasGuideColumn = true;
+ }
+ if (tokenCount == (hasGuideColumn ? 2 : 1))
+ {
+ isLowerDiagonalOnly = true;
+ }
+ }
+
+ if (hasGuideColumn)
+ {
+ /*
+ * check 'guide' symbol is the row'th letter of the alphabet
+ */
+ String symbol = scoreLine.nextToken();
+ if (symbol.length() > 1 || symbol.charAt(0) != alphabet[row])
+ {
+ err = String
+ .format("Error parsing score matrix at line %d, expected '%s' but found '%s'",
+ lineNo, alphabet[row], symbol);
+ throw new FileFormatException(err);
+ }
+ tokenCount = scoreLine.countTokens(); // excluding guide symbol
+ }
+
+ /*
+ * check the right number of values (lower diagonal or full format)
+ */
+ if (isLowerDiagonalOnly && tokenCount != row + 1)
+ {
+ err = String.format(
+ "Expected %d scores at line %d: '%s' but found %d", row + 1,
+ lineNo, data, tokenCount);
+ throw new FileFormatException(err);
+ }
+
+ if (!isLowerDiagonalOnly && tokenCount != size)
+ {
+ err = String.format(
+ "Expected %d scores at line %d: '%s' but found %d", size,
+ lineNo, data, scoreLine.countTokens());
+ throw new FileFormatException(err);
+ }
+
+ /*
+ * parse and set the values, setting the symmetrical value
+ * as well if lower diagonal format data
+ */
+ scores[row] = new float[size];
+ int col = 0;
+ String value = null;
+ while (scoreLine.hasMoreTokens())
+ {
+ try
+ {
+ value = scoreLine.nextToken();
+ scores[row][col] = Float.valueOf(value);
+ if (isLowerDiagonalOnly)
+ {
+ scores[col][row] = scores[row][col];
+ }
+ col++;
+ } catch (NumberFormatException e)
+ {
+ err = String.format(
+ "Invalid score value '%s' at line %d column %d", value,
+ lineNo, col);
+ throw new FileFormatException(err);
+ }
+ }
+ }
+
+ /**
+ * Parse the line in an aaindex file that looks like
+ *
+ * <pre>
+ * M rows = ARNDCQEGHILKMFPSTWYV, cols = ARNDCQEGHILKMFPSTWYV
+ * </pre>
+ *
+ * rejecting it if rows and cols do not match. Returns the string of
+ * characters in the row/cols alphabet.
+ *
+ * @param lineNo
+ * @param data
+ * @return
+ * @throws FileFormatException
+ */
+ protected char[] parseAAindexRowsColumns(int lineNo, String data)
+ throws FileFormatException
+ {
+ String err = "Unexpected aaIndex score matrix data at line " + lineNo
+ + ": " + data;
+
+ try
+ {
+ String[] toks = data.split(",");
+ String rowsAlphabet = toks[0].split("=")[1].trim();
+ String colsAlphabet = toks[1].split("=")[1].trim();
+ if (!rowsAlphabet.equals(colsAlphabet))
+ {
+ throw new FileFormatException("rows != cols");
+ }
+ return rowsAlphabet.toCharArray();
+ } catch (Throwable t)
+ {
+ throw new FileFormatException(err + " " + t.getMessage());
+ }
+ }
+
+ /**
+ * Answers true if line is one we are not interested in from AAindex format
+ * file
+ *
+ * @param data
+ * @return
+ */
+ protected boolean skipAAindexLine(String data)
+ {
+ if (data.startsWith(COMMENT_CHAR) || data.length() == 0)
+ {
+ return true;
+ }
+ if (data.startsWith("*") || data.startsWith("R ")
+ || data.startsWith("A ") || data.startsWith("T ")
+ || data.startsWith("J ") || data.startsWith("//"))
+ {
+ return true;
+ }
+ return false;
+ }
+
+ public String getMatrixName()
+ {
+ return matrixName;
+ }
+}
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.schemes.ResidueProperties;
+import jalview.util.Comparison;
import jalview.util.Format;
import jalview.util.MessageManager;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.StringTokenizer;
import java.util.Vector;
import com.stevesoft.pat.Regex;
private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
- private static final Regex DETECT_BRACKETS = new Regex(
- "(<|>|\\[|\\]|\\(|\\))");
+ public static final Regex DETECT_BRACKETS = new Regex(
+ "(<|>|\\[|\\]|\\(|\\)|\\{|\\})");
StringBuffer out; // output buffer
// add alignment annotation for this feature
String key = type2id(type);
+
+ /*
+ * have we added annotation rows for this type ?
+ */
+ boolean annotsAdded = false;
if (key != null)
{
if (accAnnotations != null
Vector vv = (Vector) accAnnotations.get(key);
for (int ii = 0; ii < vv.size(); ii++)
{
+ annotsAdded = true;
AlignmentAnnotation an = (AlignmentAnnotation) vv
.elementAt(ii);
seqO.addAlignmentAnnotation(an);
while (j.hasMoreElements())
{
String desc = j.nextElement().toString();
+ if ("annotations".equals(desc) && annotsAdded)
+ {
+ // don't add features if we already added an annotation row
+ continue;
+ }
String ns = content.get(desc).toString();
char[] byChar = ns.toCharArray();
for (int k = 0; k < byChar.length; k++)
{
String acc = s.stringMatched(1);
String type = s.stringMatched(2);
- String seq = new String(s.stringMatched(3));
- String description = null;
- // Check for additional information about the current annotation
- // We use a simple string tokenizer here for speed
- StringTokenizer sep = new StringTokenizer(seq, " \t");
- description = sep.nextToken();
- if (sep.hasMoreTokens())
- {
- seq = sep.nextToken();
- }
- else
- {
- seq = description;
- description = new String();
- }
- // sequence id with from-to fields
+ String oseq = s.stringMatched(3);
+ /*
+ * copy of annotation field that may be processed into whitespace chunks
+ */
+ String seq = new String(oseq);
Hashtable ann;
// Get an object with all the annotations for this sequence
ann = new Hashtable();
seqAnn.put(acc, ann);
}
+
+ // // start of block for appending annotation lines for wrapped
+ // stokchholm file
// TODO test structure, call parseAnnotationRow with vector from
// hashtable for specific sequence
+
Hashtable features;
// Get an object with all the content for an annotation
if (ann.containsKey("features"))
content = new Hashtable();
features.put(this.id2type(type), content);
}
- String ns = (String) content.get(description);
+ String ns = (String) content.get("annotation");
+
if (ns == null)
{
ns = "";
}
+ // finally, append the annotation line
ns += seq;
- content.put(description, ns);
+ content.put("annotation", ns);
+ // // end of wrapped annotation block.
+ // // Now a new row is created with the current set of data
- // if(type.equals("SS")){
Hashtable strucAnn;
if (seqAnn.containsKey(acc))
{
{
alan.visible = false;
}
- // annotations.addAll(newStruc);
+ // new annotation overwrites any existing annotation...
+
strucAnn.put(type, newStruc);
seqAnn.put(acc, strucAnn);
}
{
String convert1, convert2 = null;
- convert1 = OPEN_PAREN.replaceAll(annots);
- convert2 = CLOSE_PAREN.replaceAll(convert1);
- annots = convert2;
+ // convert1 = OPEN_PAREN.replaceAll(annots);
+ // convert2 = CLOSE_PAREN.replaceAll(convert1);
+ // annots = convert2;
String type = label;
if (label.contains("_cons"))
type = (label.indexOf("_cons") == label.length() - 5) ? label
.substring(0, label.length() - 5) : label;
}
- boolean ss = false;
+ boolean ss = false, posterior = false;
type = id2type(type);
- if (type.equals("secondary structure"))
+ if (type.equalsIgnoreCase("secondary structure"))
{
ss = true;
}
+ if (type.equalsIgnoreCase("posterior probability"))
+ {
+ posterior = true;
+ }
// decide on secondary structure or not.
Annotation[] els = new Annotation[annots.length()];
for (int i = 0; i < annots.length(); i++)
if (DETECT_BRACKETS.search(pos))
{
ann.secondaryStructure = Rna.getRNASecStrucState(pos).charAt(0);
+ ann.displayCharacter = "" + pos.charAt(0);
}
else
{
ann.secondaryStructure = ResidueProperties.getDssp3state(pos)
.charAt(0);
- }
if (ann.secondaryStructure == pos.charAt(0))
{
{
ann.displayCharacter = " " + ann.displayCharacter;
}
+ }
}
}
+ if (posterior && !ann.isWhitespace()
+ && !Comparison.isGap(pos.charAt(0)))
+ {
+ float val = 0;
+ // symbol encodes values - 0..*==0..10
+ if (pos.charAt(0) == '*')
+ {
+ val = 10;
+ }
+ else
+ {
+ val = pos.charAt(0) - '0';
+ if (val > 9)
+ {
+ val = 10;
+ }
+ }
+ ann.value = val;
+ }
els[i] = ann;
}
// output annotations
while (i < s.length && s[i] != null)
{
- if (s[i].getDatasetSequence() != null)
+ AlignmentAnnotation[] alAnot = s[i].getAnnotation();
+ if (alAnot != null)
{
- SequenceI ds = s[i].getDatasetSequence();
- AlignmentAnnotation[] alAnot;
Annotation[] ann;
- Annotation annot;
- alAnot = s[i].getAnnotation();
- String feature = "";
- if (alAnot != null)
+ for (int j = 0; j < alAnot.length; j++)
{
- for (int j = 0; j < alAnot.length; j++)
+
+ String key = type2id(alAnot[j].label);
+ boolean isrna = alAnot[j].isValidStruc();
+
+ if (isrna)
+ {
+ // hardwire to secondary structure if there is RNA secondary
+ // structure on the annotation
+ key = "SS";
+ }
+ if (key == null)
{
- if (ds.getSequenceFeatures() != null)
- {
- feature = ds.getSequenceFeatures()[0].type;
- }
- // ?bug - feature may still have previous loop value
- String key = type2id(feature);
- if (key == null)
- {
- continue;
- }
+ continue;
+ }
- // out.append("#=GR ");
- out.append(new Format("%-" + maxid + "s").form("#=GR "
- + printId(s[i], jvSuffix) + " " + key + " "));
- ann = alAnot[j].annotations;
- boolean isrna = alAnot[j].isValidStruc();
- String seq = "";
- for (int k = 0; k < ann.length; k++)
- {
- seq += outputCharacter(key, k, isrna, ann, s[i]);
- }
- out.append(seq);
- out.append(newline);
+ // out.append("#=GR ");
+ out.append(new Format("%-" + maxid + "s").form("#=GR "
+ + printId(s[i], jvSuffix) + " " + key + " "));
+ ann = alAnot[j].annotations;
+ String seq = "";
+ for (int k = 0; k < ann.length; k++)
+ {
+ seq += outputCharacter(key, k, isrna, ann, s[i]);
}
+ out.append(seq);
+ out.append(newline);
}
}
{
if (annot == null)
{
- // sensible gap character if one is available or make one up
- return sequenceI == null ? '-' : sequenceI.getCharAt(k);
+ // sensible gap character
+ return ' ';
}
else
{
if (typeIds == null)
{
typeIds = new Hashtable();
- typeIds.put("SS", "secondary structure");
- typeIds.put("SA", "surface accessibility");
+ typeIds.put("SS", "Secondary Structure");
+ typeIds.put("SA", "Surface Accessibility");
typeIds.put("TM", "transmembrane");
- typeIds.put("PP", "posterior probability");
+ typeIds.put("PP", "Posterior Probability");
typeIds.put("LI", "ligand binding");
typeIds.put("AS", "active site");
typeIds.put("IN", "intron");
typeIds.put("DE", "description");
typeIds.put("DR", "reference");
typeIds.put("LO", "look");
- typeIds.put("RF", "reference positions");
+ typeIds.put("RF", "Reference Positions");
}
}
while (e.hasMoreElements())
{
Object ll = e.nextElement();
- if (typeIds.get(ll).toString().equals(type))
+ if (typeIds.get(ll).toString().equalsIgnoreCase(type))
{
key = (String) ll;
break;
TreePanel tp = null;
if (vstree.isValidTree())
{
- tp = alignFrame.ShowNewickTree(vstree.getNewickTree(),
+ tp = alignFrame.showNewickTree(vstree.getNewickTree(),
vstree.getTitle(), vstree.getInputData(), 600,
500, t * 20 + 50, t * 20 + 50);
*/
package jalview.io.packed;
+import jalview.analysis.TreeModel;
import jalview.api.FeatureColourI;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.SequenceI;
{
// the following works because all trees are already had node/SequenceI
// associations created.
- jalview.analysis.NJTree njt = new jalview.analysis.NJTree(
- al.getSequencesArray(), nf);
+ TreeModel njt = new TreeModel(al.getSequencesArray(), null, nf);
// this just updates the displayed leaf name on the tree according to
// the SequenceIs.
njt.renameAssociatedNodes();
*/
package jalview.io.vamsas;
-import jalview.analysis.NJTree;
+import jalview.analysis.TreeBuilder;
+import jalview.analysis.TreeModel;
import jalview.bin.Cache;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
prov.getEntry(0).setUser(provEntry.getUser());
prov.getEntry(0).setApp(provEntry.getApp());
prov.getEntry(0).setDate(provEntry.getDate());
- if (tp.getTree().hasOriginalSequenceData())
+
+ AlignmentView originalData = tp.getTree().getOriginalData();
+ if (originalData != null)
{
Input vInput = new Input();
// LATER: check to see if tree input data is contained in this alignment -
// or just correctly resolve the tree's seqData to the correct alignment
// in
// the document.
- Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal,
- tp.getTree().seqData.getSequences()));
+ Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal, tp
+ .getTree().getOriginalData().getSequences()));
Object[] alsqs = new Object[alsqrefs.size()];
alsqrefs.copyInto(alsqs);
vInput.setObjRef(alsqs);
prov.getEntry(0).addParam(new Param());
prov.getEntry(0).getParam(0).setName("treeType");
prov.getEntry(0).getParam(0).setType("utf8");
- prov.getEntry(0).getParam(0).setContent("NJ"); // TODO: type of tree is a
- // general parameter
- int ranges[] = tp.getTree().seqData.getVisibleContigs();
+ prov.getEntry(0).getParam(0)
+ .setContent(TreeBuilder.NEIGHBOUR_JOINING);
+ // TODO: type of tree is a general parameter
+ int ranges[] = originalData.getVisibleContigs();
// VisibleContigs are with respect to alignment coordinates. Still need
// offsets
- int start = tp.getTree().seqData.getAlignmentOrigin();
+ int start = tp.getTree().getOriginalData().getAlignmentOrigin();
for (int r = 0; r < ranges.length; r += 2)
{
Seg visSeg = new Seg();
/**
* construct treenode mappings for mapped sequences
*
- * @param ntree
+ * @param treeModel
* @param newick
* @return
*/
- public Treenode[] makeTreeNodes(NJTree ntree, Newick newick)
+ public Treenode[] makeTreeNodes(TreeModel treeModel, Newick newick)
{
- Vector<SequenceNode> leaves = ntree.findLeaves(ntree.getTopNode());
+ Vector<SequenceNode> leaves = treeModel.findLeaves(treeModel
+ .getTopNode());
Vector tnv = new Vector();
Enumeration l = leaves.elements();
Hashtable nodespecs = new Hashtable();
bindjvvobj(tp, tree);
tree.setTitle(tp.getTitle());
Newick newick = new Newick();
- newick.setContent(tp.getTree().toString());
+ newick.setContent(tp.getTree().print());
newick.setTitle(tp.getTitle());
tree.addNewick(newick);
tree.setProvenance(makeTreeProvenance(jal, tp));
import jalview.appletgui.AlignFrame;
import jalview.bin.JalviewLite;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceGroup;
import jalview.structure.SelectionSource;
@Override
public void selection(SequenceGroup seqsel, ColumnSelection colsel,
- SelectionSource source)
+ HiddenColumns hidden, SelectionSource source)
{
// System.err.println("Testing selection event relay to jsfunction:"+_listener);
try
protected JMenu sort = new JMenu();
- protected JMenu calculateTree = new JMenu();
+ protected JMenuItem calculateTree = new JMenuItem();
protected JCheckBoxMenuItem padGapsMenuitem = new JCheckBoxMenuItem();
pairwiseAlignmentMenuItem_actionPerformed(e);
}
});
- JMenuItem PCAMenuItem = new JMenuItem(
- MessageManager.getString("label.principal_component_analysis"));
- PCAMenuItem.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- PCAMenuItem_actionPerformed(e);
- }
- });
- JMenuItem averageDistanceTreeMenuItem = new JMenuItem(
- MessageManager.getString("label.average_distance_identity"));
- averageDistanceTreeMenuItem.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- averageDistanceTreeMenuItem_actionPerformed(e);
- }
- });
- JMenuItem neighbourTreeMenuItem = new JMenuItem(
- MessageManager.getString("label.neighbour_joining_identity"));
- neighbourTreeMenuItem.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- neighbourTreeMenuItem_actionPerformed(e);
- }
- });
this.getContentPane().setLayout(new BorderLayout());
alignFrameMenuBar.setFont(new java.awt.Font("Verdana", 0, 11));
outputTextboxMenu.setText(MessageManager
.getString("label.out_to_textbox"));
-
- JMenuItem avDistanceTreeBlosumMenuItem = new JMenuItem(
- MessageManager.getString("label.average_distance_blosum62"));
- avDistanceTreeBlosumMenuItem.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- avTreeBlosumMenuItem_actionPerformed(e);
- }
- });
- JMenuItem njTreeBlosumMenuItem = new JMenuItem(
- MessageManager.getString("label.neighbour_blosum62"));
- njTreeBlosumMenuItem.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent e)
- {
- njTreeBlosumMenuItem_actionPerformed(e);
- }
- });
annotationPanelMenuItem.setActionCommand("");
annotationPanelMenuItem.setText(MessageManager
.getString("label.show_annotations"));
@Override
public void menuSelected(MenuEvent e)
{
- buildTreeMenu();
+ buildTreeSortMenu();
}
@Override
});
sortByAnnotScore.setVisible(false);
- calculateTree
- .setText(MessageManager.getString("action.calculate_tree"));
+ calculateTree.setText(MessageManager
+ .getString("action.calculate_tree_pca"));
padGapsMenuitem.setText(MessageManager.getString("label.pad_gaps"));
padGapsMenuitem.setState(jalview.bin.Cache
calculateMenu.add(calculateTree);
calculateMenu.addSeparator();
calculateMenu.add(pairwiseAlignmentMenuItem);
- calculateMenu.add(PCAMenuItem);
calculateMenu.addSeparator();
calculateMenu.add(showTranslation);
calculateMenu.add(showReverse);
// selectMenu.add(listenToViewSelections);
}
- protected void configureSelectMenu()
- {
- // TODO Auto-generated method stub
-
- }
-
/**
* Constructs the entries on the Colour menu (but does not add them to the
* menu).
{
}
- protected void PCAMenuItem_actionPerformed(ActionEvent e)
- {
- }
-
- protected void averageDistanceTreeMenuItem_actionPerformed(ActionEvent e)
- {
- }
-
protected void neighbourTreeMenuItem_actionPerformed(ActionEvent e)
{
}
- protected void njTreeBlosumMenuItem_actionPerformed(ActionEvent e)
- {
- }
-
- protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
- {
- }
-
protected void conservationMenuItem_actionPerformed(boolean selected)
{
}
}
- public void buildTreeMenu()
+ public void buildTreeSortMenu()
{
}
import jalview.api.AlignmentViewPanel;
import jalview.io.FileFormatException;
import jalview.util.MessageManager;
+import jalview.util.Platform;
import java.awt.FlowLayout;
import java.awt.Toolkit;
JMenuItem garbageCollect = new JMenuItem();
+ protected JMenuItem groovyShell;
+
+ protected JCheckBoxMenuItem experimentalFeatures;
+
protected JCheckBoxMenuItem showConsole = new JCheckBoxMenuItem();
protected JCheckBoxMenuItem showNews = new JCheckBoxMenuItem();
e.printStackTrace();
}
- if (!new jalview.util.Platform().isAMac())
+ if (!Platform.isAMac())
{
FileMenu.setMnemonic('F');
inputLocalFileMenuItem.setMnemonic('L');
showNews_actionPerformed(e);
}
});
+ groovyShell = new JMenuItem();
+ groovyShell.setText(MessageManager.getString("label.groovy_console"));
+ groovyShell.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ groovyShell_actionPerformed();
+ }
+ });
+ experimentalFeatures = new JCheckBoxMenuItem();
+ experimentalFeatures.setText(MessageManager
+ .getString("label.show_experimental"));
+ experimentalFeatures.setToolTipText(MessageManager
+ .getString("label.show_experimental_tip"));
+ experimentalFeatures.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ showExperimental_actionPerformed(experimentalFeatures.isSelected());
+ }
+ });
+
snapShotWindow.setText(MessageManager.getString("label.take_snapshot"));
snapShotWindow.addActionListener(new ActionListener()
{
toolsMenu.add(showConsole);
toolsMenu.add(showNews);
toolsMenu.add(garbageCollect);
+ toolsMenu.add(groovyShell);
+ toolsMenu.add(experimentalFeatures);
// toolsMenu.add(snapShotWindow);
inputMenu.add(inputLocalFileMenuItem);
inputMenu.add(inputURLMenuItem);
// inputMenu.add(vamsasLoad);
}
+ protected void showExperimental_actionPerformed(boolean selected)
+ {
+ }
+
+ protected void groovyShell_actionPerformed()
+ {
+ }
+
protected void snapShotWindow_actionPerformed(ActionEvent e)
{
// TODO Auto-generated method stub
GridLayout gridLayout1 = new GridLayout();
- protected JButton createNewGroup = new JButton();
+ protected JButton createFeatures = new JButton();
protected JvCacheableInputBox<String> searchBox = new JvCacheableInputBox<String>(getCacheKey());
gridLayout1.setHgap(0);
gridLayout1.setRows(3);
gridLayout1.setVgap(2);
- createNewGroup.setEnabled(false);
- createNewGroup.setFont(new java.awt.Font("Verdana", 0, 12));
- createNewGroup.setMargin(new Insets(0, 0, 0, 0));
- createNewGroup.setText(MessageManager.getString("label.new_feature"));
- createNewGroup.addActionListener(new java.awt.event.ActionListener()
+ createFeatures.setEnabled(false);
+ createFeatures.setFont(new java.awt.Font("Verdana", 0, 12));
+ createFeatures.setMargin(new Insets(0, 0, 0, 0));
+ createFeatures.setText(MessageManager.getString("label.new_feature"));
+ createFeatures.addActionListener(new java.awt.event.ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- createNewGroup_actionPerformed(e);
+ createFeatures_actionPerformed();
}
});
searchBox.setFont(new java.awt.Font("Verdana", Font.PLAIN, 12));
actionsPanel.add(findNext, null);
actionsPanel.add(findAll, null);
- actionsPanel.add(createNewGroup, null);
+ actionsPanel.add(createFeatures, null);
this.add(jLabelFind, java.awt.BorderLayout.WEST);
this.add(actionsPanel, java.awt.BorderLayout.EAST);
this.add(jPanel2, java.awt.BorderLayout.SOUTH);
}
}
- public void createNewGroup_actionPerformed(ActionEvent e)
+ public void createFeatures_actionPerformed()
{
}
protected JCheckBox scaleAsCdna = new JCheckBox();
+ protected JCheckBox fontAsCdna = new JCheckBox();
+
/**
* Creates a new GFontChooser object.
*/
fontSize.setPreferredSize(new Dimension(50, 21));
fontSize.addActionListener(new java.awt.event.ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
- fontSize_actionPerformed(e);
+ fontSize_actionPerformed();
}
});
fontStyle.setPreferredSize(new Dimension(90, 21));
fontStyle.addActionListener(new java.awt.event.ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
- fontStyle_actionPerformed(e);
+ fontStyle_actionPerformed();
}
});
fontName.setPreferredSize(new Dimension(180, 21));
fontName.addActionListener(new java.awt.event.ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
- fontName_actionPerformed(e);
+ fontName_actionPerformed();
}
});
ok.setFont(VERDANA_11PT);
ok.addActionListener(new java.awt.event.ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
- ok_actionPerformed(e);
+ ok_actionPerformed();
}
});
cancel.setFont(VERDANA_11PT);
cancel.addActionListener(new java.awt.event.ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
- cancel_actionPerformed(e);
+ cancel_actionPerformed();
}
});
defaultButton.setText(MessageManager.getString("label.set_as_default"));
defaultButton.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
- defaultButton_actionPerformed(e);
+ defaultButton_actionPerformed();
}
});
smoothFont.setFont(JvSwingUtils.getLabelFont());
smoothFont.setOpaque(false);
smoothFont.setText(MessageManager.getString("label.anti_alias_fonts"));
- smoothFont.setBounds(new Rectangle(41, 65, 260, 23));
+ smoothFont.setBounds(new Rectangle(1, 65, 300, 23));
smoothFont.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
- smoothFont_actionPerformed(e);
+ smoothFont_actionPerformed();
}
});
/*
- * Scale protein as cDNA is only visible in SplitFrame protein alignment
+ * Scale protein as cDNA is only visible in SplitFrame
*/
scaleAsCdna.setVisible(false);
scaleAsCdna.setFont(JvSwingUtils.getLabelFont());
scaleAsCdna.setOpaque(false);
scaleAsCdna.setText(MessageManager.getString("label.scale_as_cdna"));
- scaleAsCdna.setBounds(new Rectangle(41, 85, 260, 23));
+ scaleAsCdna.setBounds(new Rectangle(1, 85, 300, 23));
scaleAsCdna.addActionListener(new ActionListener()
{
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ scaleAsCdna_actionPerformed();
+ }
+ });
+
+ /*
+ * Same font for cDNA/peptide is only visible in SplitFrame
+ */
+ fontAsCdna.setVisible(false);
+ fontAsCdna.setFont(JvSwingUtils.getLabelFont());
+ fontAsCdna.setOpaque(false);
+ fontAsCdna.setText(MessageManager.getString("label.font_as_cdna"));
+ fontAsCdna.setBounds(new Rectangle(1, 105, 350, 23));
+ fontAsCdna.addActionListener(new ActionListener()
+ {
+ @Override
public void actionPerformed(ActionEvent e)
{
- scaleAsCdna_actionPerformed(e);
+ mirrorFonts_actionPerformed();
}
});
*/
JPanel jPanel4 = new JPanel();
jPanel4.setOpaque(false);
- jPanel4.setBounds(new Rectangle(24, 112, 300, 35));
+ jPanel4.setBounds(new Rectangle(24, 132, 300, 35));
jPanel4.add(defaultButton);
jPanel4.add(ok);
jPanel4.add(cancel);
this.add(smoothFont);
this.add(scaleAsCdna);
+ this.add(fontAsCdna);
this.add(jPanel3, null);
this.add(jPanel2, null);
this.add(jPanel4);
this.add(jPanel1, null);
}
- protected void scaleAsCdna_actionPerformed(ActionEvent e)
+ protected void mirrorFonts_actionPerformed()
{
}
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- protected void ok_actionPerformed(ActionEvent e)
+ protected void scaleAsCdna_actionPerformed()
{
}
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- protected void cancel_actionPerformed(ActionEvent e)
+ protected void ok_actionPerformed()
{
}
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- protected void fontName_actionPerformed(ActionEvent e)
+ protected void cancel_actionPerformed()
{
}
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- protected void fontSize_actionPerformed(ActionEvent e)
+ protected void fontName_actionPerformed()
{
}
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- protected void fontStyle_actionPerformed(ActionEvent e)
+ protected void fontSize_actionPerformed()
{
}
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- public void defaultButton_actionPerformed(ActionEvent e)
+ protected void fontStyle_actionPerformed()
{
}
- public void smoothFont_actionPerformed(ActionEvent e)
+ public void defaultButton_actionPerformed()
{
+ }
+ protected void smoothFont_actionPerformed()
+ {
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
+import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GPCAPanel extends JInternalFrame
{
- JPanel jPanel2 = new JPanel();
+ private static final Font VERDANA_12 = new Font("Verdana", 0, 12);
- JLabel jLabel1 = new JLabel();
+ protected JComboBox<String> xCombobox = new JComboBox<String>();
- JLabel jLabel2 = new JLabel();
+ protected JComboBox<String> yCombobox = new JComboBox<String>();
- JLabel jLabel3 = new JLabel();
+ protected JComboBox<String> zCombobox = new JComboBox<String>();
- protected JComboBox xCombobox = new JComboBox();
-
- protected JComboBox yCombobox = new JComboBox();
-
- protected JComboBox zCombobox = new JComboBox();
-
- protected JButton resetButton = new JButton();
-
- FlowLayout flowLayout1 = new FlowLayout();
-
- BorderLayout borderLayout1 = new BorderLayout();
-
- JMenuBar jMenuBar1 = new JMenuBar();
-
- JMenu fileMenu = new JMenu();
-
- JMenu saveMenu = new JMenu();
-
- protected JMenu scoreMatrixMenu = new JMenu();
-
- JMenuItem eps = new JMenuItem();
-
- JMenuItem png = new JMenuItem();
-
- JMenuItem print = new JMenuItem();
-
- JMenuItem outputValues = new JMenuItem();
-
- JMenuItem outputPoints = new JMenuItem();
-
- JMenuItem outputProjPoints = new JMenuItem();
+ protected JMenu scoreModelMenu = new JMenu();
protected JMenu viewMenu = new JMenu();
protected JCheckBoxMenuItem showLabels = new JCheckBoxMenuItem();
- JMenuItem bgcolour = new JMenuItem();
-
- JMenuItem originalSeqData = new JMenuItem();
-
protected JMenu associateViewsMenu = new JMenu();
protected JMenu calcSettings = new JMenu();
protected JCheckBoxMenuItem protSetting = new JCheckBoxMenuItem();
- protected JCheckBoxMenuItem jvVersionSetting = new JCheckBoxMenuItem();
-
protected JLabel statusBar = new JLabel();
- protected GridLayout statusPanelLayout = new GridLayout();
-
protected JPanel statusPanel = new JPanel();
public GPCAPanel()
yCombobox.addItem("dim " + i);
zCombobox.addItem("dim " + i);
}
-
- setJMenuBar(jMenuBar1);
}
private void jbInit() throws Exception
{
- this.getContentPane().setLayout(borderLayout1);
- jPanel2.setLayout(flowLayout1);
- jLabel1.setFont(new java.awt.Font("Verdana", 0, 12));
+ this.getContentPane().setLayout(new BorderLayout());
+ JPanel jPanel2 = new JPanel();
+ jPanel2.setLayout(new FlowLayout());
+ JLabel jLabel1 = new JLabel();
+ jLabel1.setFont(VERDANA_12);
jLabel1.setText("x=");
- jLabel2.setFont(new java.awt.Font("Verdana", 0, 12));
+ JLabel jLabel2 = new JLabel();
+ jLabel2.setFont(VERDANA_12);
jLabel2.setText("y=");
- jLabel3.setFont(new java.awt.Font("Verdana", 0, 12));
+ JLabel jLabel3 = new JLabel();
+ jLabel3.setFont(VERDANA_12);
jLabel3.setText("z=");
jPanel2.setBackground(Color.white);
jPanel2.setBorder(null);
- zCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
- zCombobox.addActionListener(new java.awt.event.ActionListener()
+ zCombobox.setFont(VERDANA_12);
+ zCombobox.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
zCombobox_actionPerformed(e);
}
});
- yCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
- yCombobox.addActionListener(new java.awt.event.ActionListener()
+ yCombobox.setFont(VERDANA_12);
+ yCombobox.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
yCombobox_actionPerformed(e);
}
});
- xCombobox.setFont(new java.awt.Font("Verdana", 0, 12));
- xCombobox.addActionListener(new java.awt.event.ActionListener()
+ xCombobox.setFont(VERDANA_12);
+ xCombobox.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
xCombobox_actionPerformed(e);
}
});
- resetButton.setFont(new java.awt.Font("Verdana", 0, 12));
+ JButton resetButton = new JButton();
+ resetButton.setFont(VERDANA_12);
resetButton.setText(MessageManager.getString("action.reset"));
- resetButton.addActionListener(new java.awt.event.ActionListener()
+ resetButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
resetButton_actionPerformed(e);
}
});
+ JMenu fileMenu = new JMenu();
fileMenu.setText(MessageManager.getString("action.file"));
+ JMenu saveMenu = new JMenu();
saveMenu.setText(MessageManager.getString("action.save_as"));
- eps.setText("EPS");
+ JMenuItem eps = new JMenuItem("EPS");
eps.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
eps_actionPerformed(e);
}
});
- png.setText("PNG");
+ JMenuItem png = new JMenuItem("PNG");
png.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
png_actionPerformed(e);
}
});
+ JMenuItem outputValues = new JMenuItem();
outputValues.setText(MessageManager.getString("label.output_values"));
outputValues.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
outputValues_actionPerformed(e);
}
});
+ JMenuItem outputPoints = new JMenuItem();
outputPoints.setText(MessageManager.getString("label.output_points"));
outputPoints.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
outputPoints_actionPerformed(e);
}
});
+ JMenuItem outputProjPoints = new JMenuItem();
outputProjPoints.setText(MessageManager
.getString("label.output_transformed_points"));
outputProjPoints.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
outputProjPoints_actionPerformed(e);
}
});
+ JMenuItem print = new JMenuItem();
+ print.setText(MessageManager.getString("action.print"));
print.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
print_actionPerformed(e);
viewMenu.setText(MessageManager.getString("action.view"));
viewMenu.addMenuListener(new MenuListener()
{
+ @Override
public void menuSelected(MenuEvent e)
{
viewMenu_menuSelected();
}
+ @Override
public void menuDeselected(MenuEvent e)
{
}
+ @Override
public void menuCanceled(MenuEvent e)
{
}
});
- scoreMatrixMenu.setText(MessageManager
+ scoreModelMenu.setText(MessageManager
.getString("label.select_score_model"));
- scoreMatrixMenu.addMenuListener(new MenuListener()
+ scoreModelMenu.addMenuListener(new MenuListener()
{
+ @Override
public void menuSelected(MenuEvent e)
{
- scoreMatrix_menuSelected();
+ scoreModel_menuSelected();
}
+ @Override
public void menuDeselected(MenuEvent e)
{
}
+ @Override
public void menuCanceled(MenuEvent e)
{
}
showLabels.setText(MessageManager.getString("label.show_labels"));
showLabels.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
showLabels_actionPerformed(e);
}
});
- print.setText(MessageManager.getString("action.print"));
+ JMenuItem bgcolour = new JMenuItem();
bgcolour.setText(MessageManager.getString("action.background_colour"));
bgcolour.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
bgcolour_actionPerformed(e);
}
});
+ JMenuItem originalSeqData = new JMenuItem();
originalSeqData.setText(MessageManager.getString("label.input_data"));
originalSeqData.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
originalSeqData_actionPerformed(e);
protSetting_actionPerfomed(arg0);
}
});
- jvVersionSetting.setText(MessageManager
- .getString("label.jalview_pca_calculation"));
- jvVersionSetting.addActionListener(new ActionListener()
- {
- @Override
- public void actionPerformed(ActionEvent arg0)
- {
- jvVersionSetting_actionPerfomed(arg0);
- }
- });
- calcSettings.add(jvVersionSetting);
+
calcSettings.add(nuclSetting);
calcSettings.add(protSetting);
- calcSettings.add(scoreMatrixMenu);
- statusPanel.setLayout(statusPanelLayout);
- statusBar.setFont(new java.awt.Font("Verdana", 0, 12));
+ calcSettings.add(scoreModelMenu);
+ statusPanel.setLayout(new GridLayout());
+ statusBar.setFont(VERDANA_12);
// statusPanel.setBackground(Color.lightGray);
// statusBar.setBackground(Color.lightGray);
// statusPanel.add(statusBar, null);
jPanel2.add(jLabel3, null);
jPanel2.add(zCombobox, null);
jPanel2.add(resetButton, null);
+
+ JMenuBar jMenuBar1 = new JMenuBar();
jMenuBar1.add(fileMenu);
jMenuBar1.add(viewMenu);
jMenuBar1.add(calcSettings);
+ setJMenuBar(jMenuBar1);
fileMenu.add(saveMenu);
fileMenu.add(outputValues);
fileMenu.add(print);
viewMenu.add(associateViewsMenu);
}
- protected void scoreMatrix_menuSelected()
+ protected void scoreModel_menuSelected()
{
// TODO Auto-generated method stub
{
}
-
- protected void jvVersionSetting_actionPerfomed(ActionEvent arg0)
- {
- // TODO Auto-generated method stub
-
- }
}
protected JComboBox<String> fontNameCB = new JComboBox<String>();
+ protected JCheckBox showOccupancy = new JCheckBox();
+
protected JCheckBox showUnconserved = new JCheckBox();
protected JCheckBox idItalics = new JCheckBox();
identity.setHorizontalTextPosition(SwingConstants.LEFT);
identity.setSelected(true);
identity.setText(MessageManager.getString("label.consensus"));
+ showOccupancy.setFont(LABEL_FONT);
+ showOccupancy.setEnabled(false);
+ showOccupancy.setHorizontalAlignment(SwingConstants.RIGHT);
+ showOccupancy.setHorizontalTextPosition(SwingConstants.LEFT);
+ showOccupancy.setSelected(true);
+ showOccupancy.setText(MessageManager.getString("label.occupancy"));
+
JLabel showGroupbits = new JLabel();
showGroupbits.setFont(LABEL_FONT);
showGroupbits.setHorizontalAlignment(SwingConstants.RIGHT);
.getString("label.database_references"));
annotations.setFont(LABEL_FONT);
annotations.setHorizontalAlignment(SwingConstants.RIGHT);
- annotations.setHorizontalTextPosition(SwingConstants.LEADING);
+ annotations.setHorizontalTextPosition(SwingConstants.LEFT);
annotations.setSelected(true);
annotations.setText(MessageManager.getString("label.show_annotations"));
- annotations.setBounds(new Rectangle(169, 12, 200, 23));
+ // annotations.setBounds(new Rectangle(169, 12, 200, 23));
annotations.addActionListener(new ActionListener()
{
@Override
sortAutocalc.setBounds(new Rectangle(290, 285, 165, 21));
JPanel annsettingsPanel = new JPanel();
- annsettingsPanel.setBounds(new Rectangle(173, 34, 320, 75));
+ annsettingsPanel.setBounds(new Rectangle(173, 13, 320, 96));
annsettingsPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
annsettingsPanel.setBorder(new EtchedBorder());
visualTab.add(annsettingsPanel);
Border jb = new EmptyBorder(1, 1, 4, 5);
+ annotations.setBorder(jb);
+ showOccupancy.setBorder(jb);
quality.setBorder(jb);
conservation.setBorder(jb);
identity.setBorder(jb);
showConsensLogo.setBorder(jb);
JPanel autoAnnotSettings = new JPanel();
- autoAnnotSettings.setLayout(new GridLayout(3, 3));
annsettingsPanel.add(autoAnnotSettings);
+ autoAnnotSettings.setLayout(new GridLayout(0, 2));
+ autoAnnotSettings.add(annotations);
autoAnnotSettings.add(quality);
+ // second row of autoannotation box
+ autoAnnotSettings = new JPanel();
+ annsettingsPanel.add(autoAnnotSettings);
+
+ autoAnnotSettings.setLayout(new GridLayout(0, 3));
autoAnnotSettings.add(conservation);
autoAnnotSettings.add(identity);
+ autoAnnotSettings.add(showOccupancy);
autoAnnotSettings.add(showGroupbits);
autoAnnotSettings.add(showGroupConservation);
autoAnnotSettings.add(showGroupConsensus);
autoAnnotSettings.add(showConsensbits);
autoAnnotSettings.add(showConsensHistogram);
autoAnnotSettings.add(showConsensLogo);
+
+
JPanel tooltipSettings = new JPanel();
tooltipSettings.setBorder(new TitledBorder(MessageManager
jPanel2.add(sortAnnLabel);
jPanel2.add(startupCheckbox);
visualTab.add(jPanel2);
- visualTab.add(annotations);
visualTab.add(startupFileTextfield);
visualTab.add(sortby);
visualTab.add(sortAnnBy);
import java.awt.BorderLayout;
import java.awt.CardLayout;
+import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
+import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
+import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextField;
+import javax.swing.ListCellRenderer;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
});
cmb_filterOption.addItemListener(this);
+
+ // add CustomComboSeparatorsRenderer to filter option combo-box
+ cmb_filterOption.setRenderer(new CustomComboSeparatorsRenderer(
+ (ListCellRenderer<Object>) cmb_filterOption.getRenderer())
+ {
+ @Override
+ protected boolean addSeparatorAfter(JList list, FilterOption value,
+ int index)
+ {
+ return value.isAddSeparatorAfter();
+ }
+ });
+
chk_invertFilter.addItemListener(this);
pnl_actions.add(chk_rememberSettings);
private String view;
- public FilterOption(String name, String value, String view)
+ private boolean addSeparatorAfter;
+
+ /**
+ * Model for structure filter option
+ *
+ * @param name
+ * - the name of the Option
+ * @param value
+ * - the value of the option
+ * @param view
+ * - the category of the filter option
+ * @param addSeparatorAfter
+ * - if true, a horizontal separator is rendered immediately after
+ * this filter option, otherwise
+ */
+ public FilterOption(String name, String value, String view,
+ boolean addSeparatorAfter)
{
this.name = name;
this.value = value;
this.view = view;
+ this.addSeparatorAfter = addSeparatorAfter;
}
public String getName()
{
return this.name;
}
+
+ public boolean isAddSeparatorAfter()
+ {
+ return addSeparatorAfter;
+ }
+
+ public void setAddSeparatorAfter(boolean addSeparatorAfter)
+ {
+ this.addSeparatorAfter = addSeparatorAfter;
+ }
}
/**
return cmb_filterOption;
}
+ /**
+ * Custom ListCellRenderer for adding a separator between different categories
+ * of structure chooser filter option drop-down.
+ *
+ * @author tcnofoegbu
+ *
+ */
+ public abstract class CustomComboSeparatorsRenderer implements
+ ListCellRenderer<Object>
+ {
+ private ListCellRenderer<Object> regent;
+
+ private JPanel separatorPanel = new JPanel(new BorderLayout());
+
+ private JSeparator jSeparator = new JSeparator();
+
+ public CustomComboSeparatorsRenderer(ListCellRenderer<Object> listCellRenderer)
+ {
+ this.regent = listCellRenderer;
+ }
+
+ @Override
+ public Component getListCellRendererComponent(JList list,
+ Object value,
+ int index, boolean isSelected, boolean cellHasFocus)
+ {
+
+ Component comp = regent.getListCellRendererComponent(list, value,
+ index, isSelected, cellHasFocus);
+ if (index != -1
+ && addSeparatorAfter(list, (FilterOption) value, index))
+ {
+ separatorPanel.removeAll();
+ separatorPanel.add(comp, BorderLayout.CENTER);
+ separatorPanel.add(jSeparator, BorderLayout.SOUTH);
+ return separatorPanel;
+ }
+ else
+ {
+ return comp;
+ }
+ }
+
+ protected abstract boolean addSeparatorAfter(JList list,
+ FilterOption value,
+ int index);
+ }
+
protected abstract void stateChanged(ItemEvent e);
protected abstract void ok_ActionPerformed();
public abstract void tabRefresh();
public abstract void validateSelections();
-}
+}
\ No newline at end of file
gridLayout.setRows(5);
okButton.setFont(new java.awt.Font("Verdana", 0, 11));
okButton.setText(MessageManager.getString("action.ok"));
- okButton.addActionListener(new java.awt.event.ActionListener()
+ okButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
});
loadbutton.setFont(new java.awt.Font("Verdana", 0, 11));
loadbutton.setText(MessageManager.getString("action.load_scheme"));
- loadbutton.addActionListener(new java.awt.event.ActionListener()
+ loadbutton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- loadbutton_actionPerformed(e);
+ loadbutton_actionPerformed();
}
});
savebutton.setFont(new java.awt.Font("Verdana", 0, 11));
savebutton.setText(MessageManager.getString("action.save_scheme"));
- savebutton.addActionListener(new java.awt.event.ActionListener()
+ savebutton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- savebutton_actionPerformed(e);
+ savebutton_actionPerformed();
}
});
cancelButton.setFont(JvSwingUtils.getLabelFont());
cancelButton.setText(MessageManager.getString("action.cancel"));
- cancelButton.addActionListener(new java.awt.event.ActionListener()
+ cancelButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
- cancelButton_actionPerformed(e);
+ cancelButton_actionPerformed();
}
});
this.setBackground(new Color(212, 208, 223));
@Override
public void actionPerformed(ActionEvent e)
{
- caseSensitive_actionPerformed(e);
+ caseSensitive_actionPerformed();
}
});
lcaseColour
* @param e
* DOCUMENT ME!
*/
- protected void loadbutton_actionPerformed(ActionEvent e)
+ protected void loadbutton_actionPerformed()
{
}
- /**
- * DOCUMENT ME!
- *
- * @param e
- * DOCUMENT ME!
- */
- protected void savebutton_actionPerformed(ActionEvent e)
+ protected boolean savebutton_actionPerformed()
{
+ return false;
}
/**
* @param e
* DOCUMENT ME!
*/
- protected void cancelButton_actionPerformed(ActionEvent e)
+ protected void cancelButton_actionPerformed()
{
}
- public void caseSensitive_actionPerformed(ActionEvent e)
+ public void caseSensitive_actionPerformed()
{
}
- public void lcaseColour_actionPerformed(ActionEvent e)
+ public void lcaseColour_actionPerformed()
{
}
}
/**
- * Creates a new Matrix object. For example
+ * Creates a new Matrix object containing a copy of the supplied array values.
+ * For example
*
* <pre>
* new Matrix(new double[][] {{2, 3, 4}, {5, 6, 7})
{
this.rows = values.length;
this.cols = this.rows == 0 ? 0 : values[0].length;
- this.value = values;
+
+ /*
+ * make a copy of the values array, for immutability
+ */
+ this.value = new double[rows][];
+ int i = 0;
+ for (double[] row : values)
+ {
+ if (row != null)
+ {
+ value[i] = new double[row.length];
+ System.arraycopy(row, 0, value[i], 0, row.length);
+ }
+ i++;
+ }
}
/**
* Returns a new matrix which is the transpose of this one
*
- * @return DOCUMENT ME!
+ * @return
*/
@Override
public MatrixI transpose()
return value[i][j];
}
+ @Override
public void setValue(int i, int j, double val)
{
value[i][j] = val;
System.arraycopy(value[i], 0, row, 0, cols);
return row;
}
+
+ /**
+ * Returns a length 2 array of {minValue, maxValue} of all values in the
+ * matrix. Returns null if the matrix is null or empty.
+ *
+ * @return
+ */
+ double[] findMinMax()
+ {
+ if (value == null)
+ {
+ return null;
+ }
+ double min = Double.MAX_VALUE;
+ double max = -Double.MAX_VALUE;
+ boolean empty = true;
+ for (double[] row : value)
+ {
+ if (row != null)
+ {
+ for (double x : row)
+ {
+ empty = false;
+ if (x > max)
+ {
+ max = x;
+ }
+ if (x < min)
+ {
+ min = x;
+ }
+ }
+ }
+ }
+ return empty ? null : new double[] { min, max };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void reverseRange(boolean maxToZero)
+ {
+ if (value == null)
+ {
+ return;
+ }
+ double[] minMax = findMinMax();
+ if (minMax == null)
+ {
+ return; // empty matrix
+ }
+ double subtractFrom = maxToZero ? minMax[1] : minMax[0] + minMax[1];
+
+ for (double[] row : value)
+ {
+ if (row != null)
+ {
+ int j = 0;
+ for (double x : row)
+ {
+ row[j] = subtractFrom - x;
+ j++;
+ }
+ }
+ }
+ }
+
+ /**
+ * Multiplies every entry in the matrix by the given value.
+ *
+ * @param
+ */
+ @Override
+ public void multiply(double by)
+ {
+ for (double[] row : value)
+ {
+ if (row != null)
+ {
+ for (int i = 0; i < row.length; i++)
+ {
+ row[i] *= by;
+ }
+ }
+ }
+ }
}
double getValue(int i, int j);
/**
+ * Sets the value at row i, colum j
+ *
+ * @param i
+ * @param j
+ * @param d
+ */
+ void setValue(int i, int j, double d);
+
+ /**
* Answers a copy of the values in the i'th row
*
* @return
void tred();
+ /**
+ * Reverses the range of the matrix values, so that the smallest values become
+ * the largest, and the largest become the smallest. This operation supports
+ * using a distance measure as a similarity measure, or vice versa.
+ * <p>
+ * If parameter <code>maxToZero</code> is true, then the maximum value becomes
+ * zero, i.e. all values are subtracted from the maximum. This is consistent
+ * with converting an identity similarity score to a distance score - the most
+ * similar (identity) corresponds to zero distance. However note that the
+ * operation is not reversible (unless the original minimum value is zero).
+ * For example a range of 10-40 would become 30-0, which would reverse a
+ * second time to 0-30. Also note that a general similarity measure (such as
+ * BLOSUM) may give different 'identity' scores for different sequences, so
+ * they cannot all convert to zero distance.
+ * <p>
+ * If parameter <code>maxToZero</code> is false, then the values are reflected
+ * about the average of {min, max} (effectively swapping min and max). This
+ * operation <em>is</em> reversible.
+ *
+ * @param maxToZero
+ */
+ void reverseRange(boolean maxToZero);
+
+ /**
+ * Multiply all entries by the given value
+ *
+ * @param d
+ */
+ void multiply(double d);
}
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.ProfilesI;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.NucleotideColourScheme;
ResidueShaderI profcolour = null;
private ColumnSelection columnSelection;
+
+ private HiddenColumns hiddenColumns;
private ProfilesI hconsensus;
profcolour = new ResidueShader(col);
}
columnSelection = av.getColumnSelection();
+ hiddenColumns = av.getAlignment().getHiddenColumns();
hconsensus = av.getSequenceConsensusHash();
complementConsensus = av.getComplementConsensusHash();
hStrucConsensus = av.getRnaStructureConsensusHash();
{
if (hasHiddenColumns)
{
- column = columnSelection.adjustForHiddenColumns(startRes + x);
+ column = hiddenColumns.adjustForHiddenColumns(startRes + x);
if (column > row_annotations.length - 1)
{
break;
column = sRes + x;
if (hasHiddenColumns)
{
- column = columnSelection.adjustForHiddenColumns(column);
+ column = hiddenColumns.adjustForHiddenColumns(column);
}
if (column > aaMax)
column = sRes + x;
if (hasHiddenColumns)
{
- column = columnSelection.adjustForHiddenColumns(column);
+ column = hiddenColumns.adjustForHiddenColumns(column);
}
if (column > aaMax)
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.renderer;
+
+import jalview.api.AlignmentColsCollectionI;
+import jalview.api.AlignmentRowsCollectionI;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceI;
+import jalview.renderer.seqfeatures.FeatureColourFinder;
+import jalview.renderer.seqfeatures.FeatureRenderer;
+import jalview.viewmodel.OverviewDimensions;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
+public class OverviewRenderer
+{
+ private FeatureColourFinder finder;
+
+ private jalview.api.SequenceRenderer sr;
+
+ // image to render on
+ private BufferedImage miniMe;
+
+ // raw number of pixels to allocate to each column
+ private float pixelsPerCol;
+
+ // raw number of pixels to allocate to each row
+ private float pixelsPerSeq;
+
+ public OverviewRenderer(jalview.api.SequenceRenderer seqRenderer,
+ FeatureRenderer fr, OverviewDimensions od)
+ // FeatureColourFinder colfinder, OverviewDimensions od)
+ {
+ sr = seqRenderer;
+ finder = new FeatureColourFinder(fr); // colfinder;
+
+ pixelsPerCol = od.getPixelsPerCol();
+ pixelsPerSeq = od.getPixelsPerSeq();
+ miniMe = new BufferedImage(od.getWidth(), od.getHeight(),
+ BufferedImage.TYPE_INT_RGB);
+ }
+
+ /**
+ * Draw alignment rows and columns onto an image
+ *
+ * @param rit
+ * Iterator over rows to be drawn
+ * @param cit
+ * Iterator over columns to be drawn
+ * @return image containing the drawing
+ */
+ public BufferedImage draw(AlignmentRowsCollectionI rows,
+ AlignmentColsCollectionI cols)
+ {
+ int rgbcolor = Color.white.getRGB();
+ int seqIndex = 0;
+ int pixelRow = 0;
+ for (int alignmentRow : rows)
+ {
+ // get details of this alignment row
+ boolean hidden = rows.isHidden(alignmentRow);
+ SequenceI seq = rows.getSequence(alignmentRow);
+
+ // calculate where this row extends to in pixels
+ int endRow = Math.min(Math.round((seqIndex + 1) * pixelsPerSeq) - 1,
+ miniMe.getHeight() - 1);
+
+ int colIndex = 0;
+ int pixelCol = 0;
+ for (int alignmentCol : cols)
+ {
+ // calculate where this column extends to in pixels
+ int endCol = Math.min(
+ Math.round((colIndex + 1) * pixelsPerCol) - 1,
+ miniMe.getWidth() - 1);
+
+ // don't do expensive colour determination if we're not going to use it
+ // NB this is important to avoid performance issues in the overview
+ // panel
+ if (pixelCol <= endCol)
+ {
+ // determine the colour based on the sequence and column position
+ rgbcolor = getColumnColourFromSequence(seq,
+ hidden || cols.isHidden(alignmentCol), alignmentCol,
+ finder);
+
+ // fill in the appropriate number of pixels
+ for (int row = pixelRow; row <= endRow; ++row)
+ {
+ for (int col = pixelCol; col <= endCol; ++col)
+ {
+ miniMe.setRGB(col, row, rgbcolor);
+ }
+ }
+
+ pixelCol = endCol + 1;
+ }
+ colIndex++;
+ }
+ pixelRow = endRow + 1;
+ seqIndex++;
+ }
+ return miniMe;
+ }
+
+ /*
+ * Find the colour of a sequence at a specified column position
+ */
+ private int getColumnColourFromSequence(jalview.datamodel.SequenceI seq,
+ boolean isHidden, int lastcol, FeatureColourFinder fcfinder)
+ {
+ Color color = Color.white;
+
+ if ((seq != null) && (seq.getLength() > lastcol))
+ {
+ color = sr.getResidueColour(seq, lastcol, fcfinder);
+ }
+
+ if (isHidden)
+ {
+ color = color.darker().darker();
+ }
+
+ return color.getRGB();
+ }
+
+ /**
+ * Draw the alignment annotation in the overview panel
+ *
+ * @param g
+ * the graphics object to draw on
+ * @param anno
+ * alignment annotation information
+ * @param charWidth
+ * alignment character width value
+ * @param y
+ * y-position for the annotation graph
+ * @param cols
+ * the collection of columns used in the overview panel
+ */
+ public void drawGraph(Graphics g, AlignmentAnnotation anno, int charWidth,
+ int y, AlignmentColsCollectionI cols)
+ {
+ Annotation[] annotations = anno.annotations;
+ g.setColor(Color.white);
+ g.fillRect(0, 0, miniMe.getWidth(), y);
+
+ int height;
+ int colIndex = 0;
+ int pixelCol = 0;
+ for (int alignmentCol : cols)
+ {
+ if (alignmentCol >= annotations.length)
+ {
+ break; // no more annotations to draw here
+ }
+ else
+ {
+ int endCol = Math.min(
+ Math.round((colIndex + 1) * pixelsPerCol) - 1,
+ miniMe.getWidth() - 1);
+
+ if (annotations[alignmentCol] != null)
+ {
+ if (annotations[alignmentCol].colour == null)
+ {
+ g.setColor(Color.black);
+ }
+ else
+ {
+ g.setColor(annotations[alignmentCol].colour);
+ }
+
+ height = (int) ((annotations[alignmentCol].value / anno.graphMax) * y);
+ if (height > y)
+ {
+ height = y;
+ }
+
+ g.fillRect(pixelCol, y - height, endCol - pixelCol + 1, height);
+ }
+ pixelCol = endCol + 1;
+ colIndex++;
+ }
+ }
+ }
+}
{
// find bounds and set origin appopriately
// locate first visible position for this sequence
- int[] refbounds = av.getColumnSelection()
+ int[] refbounds = av.getAlignment().getHiddenColumns()
.locateVisibleBoundsOfSequence(refSeq);
refSp = refbounds[0];
{
if (refSeq == null)
{
- iadj = av.getColumnSelection().adjustForHiddenColumns(i - 1) + 1;
+ iadj = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(i - 1) + 1;
string = String.valueOf(iadj);
}
else
{
- iadj = av.getColumnSelection().adjustForHiddenColumns(i - 1);
+ iadj = av.getAlignment().getHiddenColumns()
+ .adjustForHiddenColumns(i - 1);
refN = refSeq.findPosition(iadj);
// TODO show bounds if position is a gap
// - ie L--R -> "1L|2R" for
*/
package jalview.schemes;
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.api.analysis.PairwiseScoreModelI;
import jalview.datamodel.AnnotatedCollectionI;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceI;
public Color findColour(char res, int j, SequenceI seq,
String consensusResidue, float pid)
{
+ PairwiseScoreModelI sm = ScoreModels.getInstance().getBlosum62();
+
/*
* compare as upper case; note consensusResidue is
* always computed as uppercase
}
else
{
- int c = 0;
+ float score = 0;
for (char consensus : consensusResidue.toCharArray())
{
- c += ResidueProperties.getBLOSUM62(consensus, res);
+ score += sm.getPairwiseScore(consensus, res);
}
- if (c > 0)
+ if (score > 0)
{
colour = LIGHT_BLUE;
}
private static ColourSchemes instance = new ColourSchemes();
/*
- * a map from scheme name to an instance of it
+ * a map from scheme name (lower-cased) to an instance of it
*/
private Map<String, ColourSchemeI> schemes;
*/
public void removeColourScheme(String name)
{
- schemes.remove(name);
+ if (name != null)
+ {
+ schemes.remove(name.toLowerCase());
+ }
}
/**
{
return false;
}
- name = name.toLowerCase();
- for (ColourSchemeI scheme : getColourSchemes())
- {
- if (name.equals(scheme.getSchemeName().toLowerCase()))
- {
- return true;
- }
- }
- return false;
+ return schemes.containsKey(name.toLowerCase());
}
}
*/
package jalview.schemes;
-import jalview.analysis.scoremodels.FeatureScoreModel;
-import jalview.analysis.scoremodels.PIDScoreModel;
-import jalview.api.analysis.ScoreModelI;
-
import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
public class ResidueProperties
{
- public static Hashtable<String, ScoreModelI> scoreMatrices = new Hashtable<String, ScoreModelI>();
-
// Stores residue codes/names and colours and other things
public static final int[] aaIndex; // aaHash version 2.1.1 and below
// public static final double hydmax = 1.38;
// public static final double hydmin = -2.53;
- private static final int[][] BLOSUM62 = {
- { 4, -1, -2, -2, 0, -1, -1, 0, -2, -1, -1, -1, -1, -2, -1, 1, 0, -3,
- -2, 0, -2, -1, 0, -4 },
- { -1, 5, 0, -2, -3, 1, 0, -2, 0, -3, -2, 2, -1, -3, -2, -1, -1, -3,
- -2, -3, -1, 0, -1, -4 },
- { -2, 0, 6, 1, -3, 0, 0, 0, 1, -3, -3, 0, -2, -3, -2, 1, 0, -4, -2,
- -3, 3, 0, -1, -4 },
- { -2, -2, 1, 6, -3, 0, 2, -1, -1, -3, -4, -1, -3, -3, -1, 0, -1, -4,
- -3, -3, 4, 1, -1, -4 },
- { 0, -3, -3, -3, 9, -3, -4, -3, -3, -1, -1, -3, -1, -2, -3, -1, -1,
- -2, -2, -1, -3, -3, -2, -4 },
- { -1, 1, 0, 0, -3, 5, 2, -2, 0, -3, -2, 1, 0, -3, -1, 0, -1, -2, -1,
- -2, 0, 3, -1, -4 },
- { -1, 0, 0, 2, -4, 2, 5, -2, 0, -3, -3, 1, -2, -3, -1, 0, -1, -3, -2,
- -2, 1, 4, -1, -4 },
- { 0, -2, 0, -1, -3, -2, -2, 6, -2, -4, -4, -2, -3, -3, -2, 0, -2, -2,
- -3, -3, -1, -2, -1, -4 },
- { -2, 0, 1, -1, -3, 0, 0, -2, 8, -3, -3, -1, -2, -1, -2, -1, -2, -2,
- 2, -3, 0, 0, -1, -4 },
- { -1, -3, -3, -3, -1, -3, -3, -4, -3, 4, 2, -3, 1, 0, -3, -2, -1, -3,
- -1, 3, -3, -3, -1, -4 },
- { -1, -2, -3, -4, -1, -2, -3, -4, -3, 2, 4, -2, 2, 0, -3, -2, -1, -2,
- -1, 1, -4, -3, -1, -4 },
- { -1, 2, 0, -1, -3, 1, 1, -2, -1, -3, -2, 5, -1, -3, -1, 0, -1, -3,
- -2, -2, 0, 1, -1, -4 },
- { -1, -1, -2, -3, -1, 0, -2, -3, -2, 1, 2, -1, 5, 0, -2, -1, -1, -1,
- -1, 1, -3, -1, -1, -4 },
- { -2, -3, -3, -3, -2, -3, -3, -3, -1, 0, 0, -3, 0, 6, -4, -2, -2, 1,
- 3, -1, -3, -3, -1, -4 },
- { -1, -2, -2, -1, -3, -1, -1, -2, -2, -3, -3, -1, -2, -4, 7, -1, -1,
- -4, -3, -2, -2, -1, -2, -4 },
- { 1, -1, 1, 0, -1, 0, 0, 0, -1, -2, -2, 0, -1, -2, -1, 4, 1, -3, -2,
- -2, 0, 0, 0, -4 },
- { 0, -1, 0, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1, -2, -1, 1, 5, -2,
- -2, 0, -1, -1, 0, -4 },
- { -3, -3, -4, -4, -2, -2, -3, -2, -2, -3, -2, -3, -1, 1, -4, -3, -2,
- 11, 2, -3, -4, -3, -2, -4 },
- { -2, -2, -2, -3, -2, -1, -2, -3, 2, -1, -1, -2, -1, 3, -3, -2, -2,
- 2, 7, -1, -3, -2, -1, -4 },
- { 0, -3, -3, -3, -1, -2, -2, -3, -3, 3, 1, -2, 1, -1, -2, -2, 0, -3,
- -1, 4, -3, -2, -1, -4 },
- { -2, -1, 3, 4, -3, 0, 1, -1, 0, -3, -4, 0, -3, -3, -2, 0, -1, -4,
- -3, -3, 4, 1, -1, -4 },
- { -1, 0, 0, 1, -3, 3, 4, -2, 0, -3, -3, 1, -1, -3, -1, 0, -1, -3, -2,
- -2, 1, 4, -1, -4 },
- { 0, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 0, 0,
- -2, -1, -1, -1, -1, -1, -4 },
- { -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
- -4, -4, -4, -4, -4, -4, 1 }, };
-
- static final int[][] PAM250 = {
- { 2, -2, 0, 0, -2, 0, 0, 1, -1, -1, -2, -1, -1, -3, 1, 1, 1, -6, -3,
- 0, 0, 0, 0, -8 },
- { -2, 6, 0, -1, -4, 1, -1, -3, 2, -2, -3, 3, 0, -4, 0, 0, -1, 2, -4,
- -2, -1, 0, -1, -8 },
- { 0, 0, 2, 2, -4, 1, 1, 0, 2, -2, -3, 1, -2, -3, 0, 1, 0, -4, -2, -2,
- 2, 1, 0, -8 },
- { 0, -1, 2, 4, -5, 2, 3, 1, 1, -2, -4, 0, -3, -6, -1, 0, 0, -7, -4,
- -2, 3, 3, -1, -8 },
- { -2, -4, -4, -5, 12, -5, -5, -3, -3, -2, -6, -5, -5, -4, -3, 0, -2,
- -8, 0, -2, -4, -5, -3, -8 },
- { 0, 1, 1, 2, -5, 4, 2, -1, 3, -2, -2, 1, -1, -5, 0, -1, -1, -5, -4,
- -2, 1, 3, -1, -8 },
- { 0, -1, 1, 3, -5, 2, 4, 0, 1, -2, -3, 0, -2, -5, -1, 0, 0, -7, -4,
- -2, 3, 3, -1, -8 },
- { 1, -3, 0, 1, -3, -1, 0, 5, -2, -3, -4, -2, -3, -5, 0, 1, 0, -7, -5,
- -1, 0, 0, -1, -8 },
- { -1, 2, 2, 1, -3, 3, 1, -2, 6, -2, -2, 0, -2, -2, 0, -1, -1, -3, 0,
- -2, 1, 2, -1, -8 },
- { -1, -2, -2, -2, -2, -2, -2, -3, -2, 5, 2, -2, 2, 1, -2, -1, 0, -5,
- -1, 4, -2, -2, -1, -8 },
- { -2, -3, -3, -4, -6, -2, -3, -4, -2, 2, 6, -3, 4, 2, -3, -3, -2, -2,
- -1, 2, -3, -3, -1, -8 },
- { -1, 3, 1, 0, -5, 1, 0, -2, 0, -2, -3, 5, 0, -5, -1, 0, 0, -3, -4,
- -2, 1, 0, -1, -8 },
- { -1, 0, -2, -3, -5, -1, -2, -3, -2, 2, 4, 0, 6, 0, -2, -2, -1, -4,
- -2, 2, -2, -2, -1, -8 },
- { -3, -4, -3, -6, -4, -5, -5, -5, -2, 1, 2, -5, 0, 9, -5, -3, -3, 0,
- 7, -1, -4, -5, -2, -8 },
- { 1, 0, 0, -1, -3, 0, -1, 0, 0, -2, -3, -1, -2, -5, 6, 1, 0, -6, -5,
- -1, -1, 0, -1, -8 },
- { 1, 0, 1, 0, 0, -1, 0, 1, -1, -1, -3, 0, -2, -3, 1, 2, 1, -2, -3,
- -1, 0, 0, 0, -8 },
- { 1, -1, 0, 0, -2, -1, 0, 0, -1, 0, -2, 0, -1, -3, 0, 1, 3, -5, -3,
- 0, 0, -1, 0, -8 },
- { -6, 2, -4, -7, -8, -5, -7, -7, -3, -5, -2, -3, -4, 0, -6, -2, -5,
- 17, 0, -6, -5, -6, -4, -8 },
- { -3, -4, -2, -4, 0, -4, -4, -5, 0, -1, -1, -4, -2, 7, -5, -3, -3, 0,
- 10, -2, -3, -4, -2, -8 },
- { 0, -2, -2, -2, -2, -2, -2, -1, -2, 4, 2, -2, 2, -1, -1, -1, 0, -6,
- -2, 4, -2, -2, -1, -8 },
- { 0, -1, 2, 3, -4, 1, 3, 0, 1, -2, -3, 1, -2, -4, -1, 0, 0, -5, -3,
- -2, 3, 2, -1, -8 },
- { 0, 0, 1, 3, -5, 3, 3, 0, 2, -2, -3, 0, -2, -5, 0, 0, -1, -6, -4,
- -2, 2, 3, -1, -8 },
- { 0, -1, 0, -1, -3, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, 0, 0, -4,
- -2, -1, -1, -1, -1, -8 },
- { -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
- -8, -8, -8, -8, -8, -8, 1 }, };
// not currently used
// public static final Map<String, Color> ssHash = new Hashtable<String,
* Color.white, // R Color.white, // Y Color.white, // N Color.white, // Gap
*/
- // JBPNote: patch matrix for T/U equivalence when working with DNA or RNA.
- // Will equate sequences if working with mixed nucleotide sets.
- // treats T and U identically. R and Y weak equivalence with AG and CTU.
- // N matches any other base weakly
- //
- static final int[][] DNA = { { 10, -8, -8, -8, -8, 1, 1, 1, -8, 1, 1 }, // A
- { -8, 10, -8, -8, -8, 1, 1, -8, 1, 1, 1 }, // C
- { -8, -8, 10, -8, -8, 1, 1, 1, -8, 1, 1 }, // G
- { -8, -8, -8, 10, 10, 1, 1, -8, 1, 1, 1 }, // T
- { -8, -8, -8, 10, 10, 1, 1, -8, 1, 1, 1 }, // U
- { 1, 1, 1, 1, 1, 10, 0, 0, 0, 1, 1 }, // I
- { 1, 1, 1, 1, 1, 0, 10, 0, 0, 1, 1 }, // X
- { 1, -8, 1, -8, -8, 0, 0, 10, -8, 1, 1 }, // R
- { -8, 1, -8, 1, 1, 0, 0, -8, 10, 1, 1 }, // Y
- { 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 1 }, // N
- { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // -
- };
- /**
- * register matrices in list
- */
- static
- {
- scoreMatrices.put("BLOSUM62", new ScoreMatrix("BLOSUM62", BLOSUM62, 0));
- scoreMatrices.put("PAM250", new ScoreMatrix("PAM250", PAM250, 0));
- scoreMatrices.put("DNA", new ScoreMatrix("DNA", DNA, 1));
- }
-
public static List<String> STOP = Arrays.asList("TGA", "TAA", "TAG");
public static String START = "ATG";
propMatrixPos[i][i] = maxP;
propMatrixEpos[i][i] = maxEP;
}
- // JAL-1512 comment out physicochemical score matrices for 2.8.1 release
- // scoreMatrices.put("Conservation Pos", new
- // ScoreMatrix("Conservation Pos",propMatrixPos,0));
- // scoreMatrices.put("Conservation Both", new
- // ScoreMatrix("Conservation Both",propMatrixF,0));
- // scoreMatrices.put("Conservation EnhPos", new
- // ScoreMatrix("Conservation EnhPos",propMatrixEpos,0));
- scoreMatrices.put("PID", new PIDScoreModel());
- scoreMatrices.put("Displayed Features", new FeatureScoreModel());
}
private ResidueProperties()
return aa3Hash;
}
- public static int[][] getDNA()
- {
- return ResidueProperties.DNA;
- }
-
- public static int[][] getBLOSUM62()
- {
- return ResidueProperties.BLOSUM62;
- }
-
- public static int getPAM250(String A1, String A2)
- {
- return getPAM250(A1.charAt(0), A2.charAt(0));
- }
-
- public static int getBLOSUM62(char c1, char c2)
- {
- int pog = 0;
-
- try
- {
- int a = aaIndex[c1];
- int b = aaIndex[c2];
-
- pog = ResidueProperties.BLOSUM62[a][b];
- } catch (Exception e)
- {
- // System.out.println("Unknown residue in " + A1 + " " + A2);
- }
-
- return pog;
- }
-
public static String codonTranslate(String lccodon)
{
String cdn = codonHash2.get(lccodon.toUpperCase());
return cdn;
}
- public static int[][] getDefaultPeptideMatrix()
- {
- return ResidueProperties.getBLOSUM62();
- }
-
- public static int[][] getDefaultDnaMatrix()
- {
- return ResidueProperties.getDNA();
- }
-
- /**
- * get a ScoreMatrix based on its string name
- *
- * @param pwtype
- * @return matrix in scoreMatrices with key pwtype or null
- */
- public static ScoreMatrix getScoreMatrix(String pwtype)
- {
- Object val = scoreMatrices.get(pwtype);
- if (val != null && val instanceof ScoreMatrix)
- {
- return (ScoreMatrix) val;
- }
- return null;
- }
-
- /**
- * get a ScoreModel based on its string name
- *
- * @param pwtype
- * @return scoremodel of type pwtype or null
- */
- public static ScoreModelI getScoreModel(String pwtype)
- {
- return scoreMatrices.get(pwtype);
- }
-
- public static int getPAM250(char c, char d)
- {
- int a = aaIndex[c];
- int b = aaIndex[d];
-
- int pog = ResidueProperties.PAM250[a][b];
-
- return pog;
- }
-
public static Hashtable<String, String> toDssp3State;
static
{
+++ /dev/null
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- *
- * This file is part of Jalview.
- *
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-package jalview.schemes;
-
-import jalview.analysis.scoremodels.PairwiseSeqScoreModel;
-import jalview.math.Matrix;
-import jalview.math.MatrixI;
-
-public class ScoreMatrix extends PairwiseSeqScoreModel
-{
- String name;
-
- @Override
- public String getName()
- {
- return name;
- }
-
- /**
- * reference to integer score matrix
- */
- int[][] matrix;
-
- /**
- * 0 for Protein Score matrix. 1 for dna score matrix
- */
- int type;
-
- /**
- *
- * @param name
- * Unique, human readable name for the matrix
- * @param matrix
- * Pairwise scores indexed according to appropriate symbol alphabet
- * @param type
- * 0 for Protein, 1 for NA
- */
- ScoreMatrix(String name, int[][] matrix, int type)
- {
- this.matrix = matrix;
- this.type = type;
- this.name = name;
- }
-
- @Override
- public boolean isDNA()
- {
- return type == 1;
- }
-
- @Override
- public boolean isProtein()
- {
- return type == 0;
- }
-
- @Override
- public int[][] getMatrix()
- {
- return matrix;
- }
-
- /**
- * Answers the score for substituting first char in A1 with first char in A2
- *
- * @param A1
- * @param A2
- * @return
- */
- public int getPairwiseScore(String A1, String A2)
- {
- return getPairwiseScore(A1.charAt(0), A2.charAt(0));
- }
-
- @Override
- public int getPairwiseScore(char c, char d)
- {
- int score = 0;
-
- try
- {
- int a = (type == 0) ? ResidueProperties.aaIndex[c]
- : ResidueProperties.nucleotideIndex[c];
- int b = (type == 0) ? ResidueProperties.aaIndex[d]
- : ResidueProperties.nucleotideIndex[d];
- score = matrix[a][b];
- } catch (Exception e)
- {
- // System.out.println("Unknown residue in " + A1 + " " + A2);
- }
-
- return score;
- }
-
- /**
- * pretty print the matrix
- */
- @Override
- public String toString()
- {
- return outputMatrix(false);
- }
-
- public String outputMatrix(boolean html)
- {
- StringBuffer sb = new StringBuffer();
- int[] symbols = (type == 0) ? ResidueProperties.aaIndex
- : ResidueProperties.nucleotideIndex;
- int symMax = (type == 0) ? ResidueProperties.maxProteinIndex
- : ResidueProperties.maxNucleotideIndex;
- boolean header = true;
- if (html)
- {
- sb.append("<table border=\"1\">");
- }
- for (char sym = 'A'; sym <= 'Z'; sym++)
- {
- if (symbols[sym] >= 0 && symbols[sym] < symMax)
- {
- if (header)
- {
- sb.append(html ? "<tr><td></td>" : "");
- for (char sym2 = 'A'; sym2 <= 'Z'; sym2++)
- {
- if (symbols[sym2] >= 0 && symbols[sym2] < symMax)
- {
- sb.append((html ? "<td> " : "\t") + sym2
- + (html ? " </td>" : ""));
- }
- }
- header = false;
- sb.append(html ? "</tr>\n" : "\n");
- }
- if (html)
- {
- sb.append("<tr>");
- }
- sb.append((html ? "<td>" : "") + sym + (html ? "</td>" : ""));
- for (char sym2 = 'A'; sym2 <= 'Z'; sym2++)
- {
- if (symbols[sym2] >= 0 && symbols[sym2] < symMax)
- {
- sb.append((html ? "<td>" : "\t")
- + matrix[symbols[sym]][symbols[sym2]]
- + (html ? "</td>" : ""));
- }
- }
- sb.append(html ? "</tr>\n" : "\n");
- }
- }
- if (html)
- {
- sb.append("</table>");
- }
- return sb.toString();
- }
-
- /**
- * Computes an NxN matrix where N is the number of sequences, and entry [i, j]
- * is sequence[i] pairwise multiplied with sequence[j], as a sum of scores
- * computed using the current score matrix. For example
- * <ul>
- * <li>Sequences:</li>
- * <li>FKL</li>
- * <li>R-D</li>
- * <li>QIA</li>
- * <li>GWC</li>
- * <li>Score matrix is BLOSUM62</li>
- * <li>Gaps treated same as X (unknown)</li>
- * <li>product [0, 0] = F.F + K.K + L.L = 6 + 5 + 4 = 15</li>
- * <li>product [1, 1] = R.R + -.- + D.D = 5 + -1 + 6 = 10</li>
- * <li>product [2, 2] = Q.Q + I.I + A.A = 5 + 4 + 4 = 13</li>
- * <li>product [3, 3] = G.G + W.W + C.C = 6 + 11 + 9 = 26</li>
- * <li>product[0, 1] = F.R + K.- + L.D = -3 + -1 + -3 = -8
- * <li>and so on</li>
- * </ul>
- */
- public MatrixI computePairwiseScores(String[] seqs)
- {
- double[][] values = new double[seqs.length][];
- for (int row = 0; row < seqs.length; row++)
- {
- values[row] = new double[seqs.length];
- for (int col = 0; col < seqs.length; col++)
- {
- int total = 0;
- int width = Math.min(seqs[row].length(), seqs[col].length());
- for (int i = 0; i < width; i++)
- {
- char c1 = seqs[row].charAt(i);
- char c2 = seqs[col].charAt(i);
- int score = getPairwiseScore(c1, c2);
- total += score;
- }
- values[row][col] = total;
- }
- }
- return new Matrix(values);
- }
-}
* - source of the selection event
*/
public void selection(jalview.datamodel.SequenceGroup seqsel,
- jalview.datamodel.ColumnSelection colsel, SelectionSource source);
+ jalview.datamodel.ColumnSelection colsel,
+ jalview.datamodel.HiddenColumns hidden,
+ SelectionSource source);
}
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
* Attempt pairwise alignment of the sequence with each chain in the PDB,
* and remember the highest scoring chain
*/
- int max = -10;
+ float max = -10;
AlignSeq maxAlignseq = null;
String maxChainId = " ";
PDBChain maxChain = null;
public synchronized void sendSelection(
jalview.datamodel.SequenceGroup selection,
- jalview.datamodel.ColumnSelection colsel, SelectionSource source)
+ jalview.datamodel.ColumnSelection colsel, HiddenColumns hidden,
+ SelectionSource source)
{
for (SelectionListener slis : sel_listeners)
{
if (slis != source)
{
- slis.selection(selection, colsel, source);
+ slis.selection(selection, colsel, hidden, source);
}
}
}
import jalview.api.StructureSelectionManagerProvider;
import jalview.api.structures.JalviewStructureDisplayI;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.SequenceI;
import jalview.io.DataSourceType;
* an array of corresponding hidden columns for each alignment
* @return
*/
- public abstract String superposeStructures(AlignmentI[] alignments, int[] structureIndices,
- ColumnSelection[] hiddenCols);
+ public abstract String superposeStructures(AlignmentI[] alignments,
+ int[] structureIndices, HiddenColumns[] hiddenCols);
public abstract void setBackgroundColour(Color col);
private static final int TO_UPPER_CASE = 'a' - 'A';
- private static final char GAP_SPACE = ' ';
+ public static final char GAP_SPACE = ' ';
- private static final char GAP_DOT = '.';
+ public static final char GAP_DOT = '.';
- private static final char GAP_DASH = '-';
+ public static final char GAP_DASH = '-';
public static final String GapChars = new String(new char[] { GAP_SPACE,
GAP_DOT, GAP_DASH });
* @param s2
* SequenceI
* @return float
+ * @deprecated use PIDModel.computePID()
*/
+ @Deprecated
public final static float PID(String seq1, String seq2)
{
return PID(seq1, seq2, 0, seq1.length());
static final int caseShift = 'a' - 'A';
// Another pid with region specification
+ /**
+ * @deprecated use PIDModel.computePID()
+ */
+ @Deprecated
public final static float PID(String seq1, String seq2, int start, int end)
{
return PID(seq1, seq2, start, end, true, false);
* @param ungappedOnly
* - if true - only count PID over ungapped columns
* @return
+ * @deprecated use PIDModel.computePID()
*/
+ @Deprecated
public final static float PID(String seq1, String seq2, int start,
int end, boolean wcGaps, boolean ungappedOnly)
{
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
* @param mapTo
* @return
*/
- public static ColumnSelection mapColumnSelection(ColumnSelection colsel,
- AlignViewportI mapFrom, AlignViewportI mapTo)
+ public static void mapColumnSelection(ColumnSelection colsel,
+ HiddenColumns hiddencols, AlignViewportI mapFrom,
+ AlignViewportI mapTo, ColumnSelection newColSel,
+ HiddenColumns newHidden)
{
boolean targetIsNucleotide = mapTo.isNucleotide();
AlignViewportI protein = targetIsNucleotide ? mapFrom : mapTo;
List<AlignedCodonFrame> codonFrames = protein.getAlignment()
.getCodonFrames();
- ColumnSelection mappedColumns = new ColumnSelection();
+ // ColumnSelection mappedColumns = new ColumnSelection();
if (colsel == null)
{
- return mappedColumns;
+ return; // mappedColumns;
}
char fromGapChar = mapFrom.getAlignment().getGapCharacter();
for (Integer sel : colsel.getSelected())
{
- mapColumn(sel.intValue(), codonFrames, mappedColumns, fromSequences,
+ mapColumn(sel.intValue(), codonFrames, newColSel, fromSequences,
toSequences, fromGapChar);
}
- for (int[] hidden : colsel.getHiddenColumns())
+ for (int[] hidden : hiddencols.getHiddenRegions())
{
- mapHiddenColumns(hidden, codonFrames, mappedColumns, fromSequences,
+ mapHiddenColumns(hidden, codonFrames, newHidden, fromSequences,
toSequences, fromGapChar);
}
- return mappedColumns;
+ return; // mappedColumns;
}
/**
* @param fromGapChar
*/
protected static void mapHiddenColumns(int[] hidden,
- List<AlignedCodonFrame> mappings, ColumnSelection mappedColumns,
+ List<AlignedCodonFrame> mappings, HiddenColumns mappedColumns,
List<SequenceI> fromSequences, List<SequenceI> toSequences,
char fromGapChar)
{
--- /dev/null
+package jalview.util;
+
+import java.util.Set;
+
+public class SetUtils
+{
+ /**
+ * Returns the count of things that are in one or other of two sets but not in
+ * both. The sets are not modified.
+ *
+ * @param set1
+ * @param set2
+ * @return
+ */
+ public static int countDisjunction(Set<? extends Object> set1,
+ Set<? extends Object> set2)
+ {
+ if (set1 == null)
+ {
+ return set2 == null ? 0 : set2.size();
+ }
+ if (set2 == null)
+ {
+ return set1.size();
+ }
+
+ int size1 = set1.size();
+ int size2 = set2.size();
+ Set<? extends Object> smallerSet = size1 < size2 ? set1 : set2;
+ Set<? extends Object> largerSet = (smallerSet == set1 ? set2 : set1);
+ int inCommon = 0;
+ for (Object k : smallerSet)
+ {
+ if (largerSet.contains(k))
+ {
+ inCommon++;
+ }
+ }
+
+ int notInCommon = (size1 - inCommon) + (size2 - inCommon);
+ return notInCommon;
+ }
+}
*/
package jalview.viewmodel;
-import java.awt.Color;
-import java.beans.PropertyChangeSupport;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Deque;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
import jalview.analysis.Conservation;
import jalview.api.AlignCalcManagerI;
import jalview.datamodel.Annotation;
import jalview.datamodel.CigarArray;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.HiddenSequences;
import jalview.datamodel.ProfilesI;
import jalview.datamodel.SearchResultsI;
import jalview.util.Comparison;
import jalview.util.MapList;
import jalview.util.MappingUtils;
+import jalview.util.MessageManager;
import jalview.viewmodel.styles.ViewStyle;
import jalview.workers.AlignCalcManager;
import jalview.workers.ComplementConsensusThread;
import jalview.workers.ConsensusThread;
import jalview.workers.StrucConsensusThread;
+import java.awt.Color;
+import java.beans.PropertyChangeSupport;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
/**
* base class holding visualization and analysis attributes and common logic for
* an active alignment view displayed in the GUI
public abstract class AlignmentViewport implements AlignViewportI,
CommandListener, VamsasSource
{
- protected ViewportRanges ranges;
+ final protected ViewportRanges ranges;
protected ViewStyleI viewStyle = new ViewStyle();
protected Deque<CommandI> redoList = new ArrayDeque<CommandI>();
/**
+ * alignment displayed in the viewport. Please use get/setter
+ */
+ protected AlignmentI alignment;
+
+ public AlignmentViewport(AlignmentI al)
+ {
+ setAlignment(al);
+ ranges = new ViewportRanges(al);
+ }
+
+ /**
* @param name
* @see jalview.api.ViewStyleI#setFontName(java.lang.String)
*/
viewStyle.setSeqNameItalics(default1);
}
- /**
- * alignment displayed in the viewport. Please use get/setter
- */
- protected AlignmentI alignment;
+
@Override
public AlignmentI getAlignment()
protected boolean ignoreGapsInConsensusCalculation = false;
- protected ResidueShaderI residueShading;
+ protected ResidueShaderI residueShading = new ResidueShader();
@Override
public void setGlobalColourScheme(ColourSchemeI cs)
public void updateConsensus(final AlignmentViewPanel ap)
{
// see note in mantis : issue number 8585
- if ((consensus == null || gapcounts == null) || !autoCalculateConsensus)
+ if (consensus == null || !autoCalculateConsensus)
{
return;
}
}
}
- public void setHiddenColumns(ColumnSelection colsel)
+ public void setHiddenColumns(HiddenColumns hidden)
{
- this.colSel = colsel;
+ this.alignment.setHiddenColumns(hidden);
+ // this.colSel = colsel;
}
@Override
@Override
public boolean hasHiddenColumns()
{
- return colSel != null && colSel.hasHiddenColumns();
+ return colSel != null
+ && alignment.getHiddenColumns().hasHiddenColumns();
}
public void updateHiddenColumns()
protected boolean showConsensus = true;
+ protected boolean showOccupancy = true;
+
private Map<SequenceI, Color> sequenceColours = new HashMap<SequenceI, Color>();
protected SequenceAnnotationOrder sortAnnotationsBy = null;
return;
}
- colSel.hideSelectedColumns();
+ colSel.hideSelectedColumns(alignment);
setSelectionGroup(null);
isColSelChanged(true);
}
{
if (start == end)
{
- colSel.hideColumns(start);
+ colSel.hideSelectedColumns(start, alignment.getHiddenColumns());
}
else
{
- colSel.hideColumns(start, end);
+ alignment.getHiddenColumns().hideColumns(start, end);
}
isColSelChanged(true);
}
public void showColumn(int col)
{
- colSel.revealHiddenColumns(col);
+ alignment.getHiddenColumns().revealHiddenColumns(col, colSel);
isColSelChanged(true);
}
public void showAllHiddenColumns()
{
- colSel.revealAllHiddenColumns();
+ alignment.getHiddenColumns().revealAllHiddenColumns(colSel);
isColSelChanged(true);
}
@Override
public void invertColumnSelection()
{
- colSel.invertColumnSelection(0, alignment.getWidth());
+ colSel.invertColumnSelection(0, alignment.getWidth(), alignment);
}
@Override
@Override
public CigarArray getViewAsCigars(boolean selectedRegionOnly)
{
- return new CigarArray(alignment, colSel,
+ return new CigarArray(alignment, alignment.getHiddenColumns(),
(selectedRegionOnly ? selectionGroup : null));
}
public jalview.datamodel.AlignmentView getAlignmentView(
boolean selectedOnly, boolean markGroups)
{
- return new AlignmentView(alignment, colSel, selectionGroup,
- colSel != null && colSel.hasHiddenColumns(), selectedOnly,
+ return new AlignmentView(alignment, alignment.getHiddenColumns(),
+ selectionGroup, alignment.getHiddenColumns() != null
+ && alignment.getHiddenColumns().hasHiddenColumns(),
+ selectedOnly,
markGroups);
}
}
selection = new String[iSize];
- if (colSel != null && colSel.hasHiddenColumns())
+ if (alignment.getHiddenColumns() != null
+ && alignment.getHiddenColumns().hasHiddenColumns())
{
- selection = colSel.getVisibleSequenceStrings(start, end, seqs);
+ selection = alignment.getHiddenColumns().getVisibleSequenceStrings(
+ start, end, seqs);
}
else
{
do
{
- if (colSel != null && colSel.hasHiddenColumns())
+ HiddenColumns hidden = alignment.getHiddenColumns();
+ if (hidden != null && hidden.hasHiddenColumns())
{
if (start == 0)
{
- start = colSel.adjustForHiddenColumns(start);
+ start = hidden.adjustForHiddenColumns(start);
}
- end = colSel.getHiddenBoundaryRight(start);
+ end = hidden.getHiddenBoundaryRight(start);
if (start == end)
{
end = max;
regions.add(new int[] { start, end });
- if (colSel != null && colSel.hasHiddenColumns())
+ if (hidden != null && hidden.hasHiddenColumns())
{
- start = colSel.adjustForHiddenColumns(end);
- start = colSel.getHiddenBoundaryLeft(start) + 1;
+ start = hidden.adjustForHiddenColumns(end);
+ start = hidden.getHiddenBoundaryLeft(start) + 1;
}
} while (end < max);
AlignmentAnnotation clone = new AlignmentAnnotation(annot);
if (selectedOnly && selectionGroup != null)
{
- colSel.makeVisibleAnnotation(selectionGroup.getStartRes(),
+ alignment.getHiddenColumns().makeVisibleAnnotation(
+ selectionGroup.getStartRes(),
selectionGroup.getEndRes(), clone);
}
else
{
- colSel.makeVisibleAnnotation(clone);
+ alignment.getHiddenColumns().makeVisibleAnnotation(clone);
}
ala.add(clone);
}
{
initRNAStructure();
}
- consensus = new AlignmentAnnotation("Consensus", "PID",
+ consensus = new AlignmentAnnotation("Consensus",
+ MessageManager.getString("label.consensus_descr"),
new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
initConsensus(consensus);
- gapcounts = new AlignmentAnnotation("Occupancy",
- "Number of aligned positions",
- new Annotation[1], 0f, alignment.getHeight(),
- AlignmentAnnotation.BAR_GRAPH);
- initGapCounts(gapcounts);
+ initGapCounts();
initComplementConsensus();
}
if (doConsensus)
{
complementConsensus = new AlignmentAnnotation("cDNA Consensus",
- "PID for cDNA", new Annotation[1], 0f, 100f,
+ MessageManager
+ .getString("label.complement_consensus_descr"),
+ new Annotation[1], 0f, 100f,
AlignmentAnnotation.BAR_GRAPH);
initConsensus(complementConsensus);
return true;
// these should be extracted from the view model - style and settings for
// derived annotation
- private void initGapCounts(AlignmentAnnotation counts)
+ private void initGapCounts()
{
- counts.hasText = false;
- counts.autoCalculated = true;
- counts.graph = AlignmentAnnotation.BAR_GRAPH;
-
- if (showConsensus)
+ if (showOccupancy)
{
- alignment.addAnnotation(counts);
+ gapcounts = new AlignmentAnnotation("Occupancy",
+ MessageManager.getString("label.occupancy_descr"),
+ new Annotation[1], 0f,
+ alignment.getHeight(), AlignmentAnnotation.BAR_GRAPH);
+ gapcounts.hasText = true;
+ gapcounts.autoCalculated = true;
+ gapcounts.scaleColLabel = true;
+ gapcounts.graph = AlignmentAnnotation.BAR_GRAPH;
+
+ alignment.addAnnotation(gapcounts);
}
}
if (conservation == null)
{
conservation = new AlignmentAnnotation("Conservation",
- "Conservation of total alignment less than "
- + getConsPercGaps() + "% gaps", new Annotation[1],
+ MessageManager.formatMessage("label.conservation_descr",
+ getConsPercGaps()), new Annotation[1],
0f, 11f, AlignmentAnnotation.BAR_GRAPH);
conservation.hasText = true;
conservation.autoCalculated = true;
if (quality == null)
{
quality = new AlignmentAnnotation("Quality",
- "Alignment Quality based on Blosum62 scores",
+ MessageManager.getString("label.quality_descr"),
new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
quality.hasText = true;
quality.autoCalculated = true;
{
if (alignment.hasRNAStructure() && strucConsensus == null)
{
- strucConsensus = new AlignmentAnnotation("StrucConsensus", "PID",
+ strucConsensus = new AlignmentAnnotation("StrucConsensus",
+ MessageManager.getString("label.strucconsensus_descr"),
new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
strucConsensus.hasText = true;
strucConsensus.autoCalculated = true;
viewStyle.setScaleProteinAsCdna(b);
}
+ @Override
+ public boolean isProteinFontAsCdna()
+ {
+ return viewStyle.isProteinFontAsCdna();
+ }
+
+ @Override
+ public void setProteinFontAsCdna(boolean b)
+ {
+ viewStyle.setProteinFontAsCdna(b);
+ }
+
/**
* @return true if view should scroll to show the highlighted region of a
* sequence
*/
package jalview.viewmodel;
-import jalview.datamodel.ColumnSelection;
+import jalview.api.AlignmentColsCollectionI;
+import jalview.api.AlignmentRowsCollectionI;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.HiddenSequences;
import java.awt.Graphics;
-public class OverviewDimensions
+public abstract class OverviewDimensions
{
- // Default width and height values
- private static final int DEFAULT_GRAPH_HEIGHT = 20;
-
- private static final int MAX_WIDTH = 400;
-
- private static final int MIN_WIDTH = 120;
-
- private static final int MIN_SEQ_HEIGHT = 40;
-
- private static final int MAX_SEQ_HEIGHT = 300;
-
- // width of the overview panel
- private int width;
-
- // height of sequences part of the overview panel
- private int sequencesHeight;
-
- // height of the graphs part of the overview panel
- private int graphHeight = DEFAULT_GRAPH_HEIGHT;
-
- // dimensions of box outlining current extent of view in alignment panel
- // location of left side of box
- private int boxX = -1;
-
- // location of bottom of box
- private int boxY = -1;
+ protected static final int MAX_WIDTH = 400;
+ protected static final int MIN_WIDTH = 120;
+ protected static final int MIN_SEQ_HEIGHT = 40;
+ protected static final int MAX_SEQ_HEIGHT = 300;
- // width of box
- private int boxWidth = -1;
-
- // height of box
- private int boxHeight = -1;
-
- // scroll position in viewport corresponding to boxX
- private int scrollCol = -1;
+ private static final int DEFAULT_GRAPH_HEIGHT = 20;
- // scroll position in viewport corresponding to boxY
- private int scrollRow = -1;
+ protected int width;
+ protected int sequencesHeight;
+ protected int graphHeight = DEFAULT_GRAPH_HEIGHT;
+ protected int boxX = -1;
+ protected int boxY = -1;
+ protected int boxWidth = -1;
+ protected int boxHeight = -1;
+ protected int scrollCol = -1;
+ protected int scrollRow = -1;
+ protected int alwidth;
+ protected int alheight;
- /**
- * Create an OverviewDimensions object
- *
- * @param ranges
- * positional properties of the viewport
- * @param showAnnotationPanel
- * true if the annotation panel is to be shown, false otherwise
- */
public OverviewDimensions(ViewportRanges ranges,
boolean showAnnotationPanel)
{
}
/**
- * Check box dimensions and scroll positions and correct if necessary
- *
- * @param mousex
- * x position in overview panel
- * @param mousey
- * y position in overview panel
- * @param hiddenSeqs
- * hidden sequences
- * @param hiddenCols
- * hidden columns
- * @param ranges
- * viewport position properties
- */
- public void updateViewportFromMouse(int mousex, int mousey,
- HiddenSequences hiddenSeqs, ColumnSelection hiddenCols,
- ViewportRanges ranges)
- {
- int x = mousex;
- int y = mousey;
-
- int alwidth = ranges.getAbsoluteAlignmentWidth();
- int alheight = ranges.getAbsoluteAlignmentHeight();
-
- if (x < 0)
- {
- x = 0;
- }
-
- if (y < 0)
- {
- y = 0;
- }
-
- //
- // Convert x value to residue position
- //
-
- // need to determine where scrollCol should be, given x
- // to do this also need to know width of viewport, and some hidden column
- // correction
-
- // convert x to residues - this is an absolute position
- int xAsRes = Math.round((float) x * alwidth / width);
-
- // get viewport width in residues
- int vpwidth = ranges.getEndRes() - ranges.getStartRes() + 1;
-
- // get where x should be when accounting for hidden cols
- // if x is in a hidden col region, shift to left - but we still need
- // absolute position
- // so convert back after getting visible region position
- int visXAsRes = hiddenCols.findColumnPosition(xAsRes);
-
- // check in case we went off the edge of the alignment
- int visAlignWidth = hiddenCols.findColumnPosition(alwidth - 1);
- if (visXAsRes + vpwidth - 1 > visAlignWidth)
- {
- // went past the end of the alignment, adjust backwards
-
- // if last position was before the end of the alignment, need to update
- if ((scrollCol + vpwidth - 1) < visAlignWidth)
- {
- visXAsRes = hiddenCols.findColumnPosition(hiddenCols
- .subtractVisibleColumns(vpwidth - 1, alwidth - 1));
- }
- else
- {
- visXAsRes = scrollCol;
- }
- }
-
- //
- // Convert y value to sequence position
- //
-
- // convert y to residues
- int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
-
- // get viewport height in sequences
- // add 1 because height includes both endSeq and startSeq
- int vpheight = ranges.getEndSeq() - ranges.getStartSeq() + 1;
-
- // get where y should be when accounting for hidden rows
- // if y is in a hidden row region, shift up - but we still need absolute
- // position,
- // so convert back after getting visible region position
- yAsSeq = hiddenSeqs.adjustForHiddenSeqs(hiddenSeqs
- .findIndexWithoutHiddenSeqs(yAsSeq));
-
- // check in case we went off the edge of the alignment
- int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
- int visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
- if (visYAsRes + vpheight - 1 > visAlignHeight)
- {
- // went past the end of the alignment, adjust backwards
- if ((scrollRow + vpheight - 1) < visAlignHeight)
- {
- visYAsRes = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs
- .subtractVisibleRows(vpheight - 1, alheight - 1));
- }
- else
- {
- visYAsRes = scrollRow;
- }
- }
-
- // update scroll values
- scrollCol = visXAsRes;
- scrollRow = visYAsRes;
-
- }
-
- /**
- * Update the overview panel box when the associated alignment panel is
- * changed
- *
- * @param hiddenSeqs
- * hidden sequences
- * @param hiddenCols
- * hidden columns
- * @param ranges
- * viewport position properties
- */
- public void setBoxPosition(HiddenSequences hiddenSeqs,
- ColumnSelection hiddenCols, ViewportRanges ranges)
- {
- int alwidth = ranges.getAbsoluteAlignmentWidth();
- int alheight = ranges.getAbsoluteAlignmentHeight();
-
- // work with absolute values of startRes and endRes
- int startRes = hiddenCols.adjustForHiddenColumns(ranges.getStartRes());
- int endRes = hiddenCols.adjustForHiddenColumns(ranges.getEndRes());
-
- // work with absolute values of startSeq and endSeq
- int startSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getStartSeq());
- int endSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getEndSeq());
-
- // boxX, boxY is the x,y location equivalent to startRes, startSeq
- boxX = Math.round((float) startRes * width / alwidth);
- boxY = Math.round((float) startSeq * sequencesHeight / alheight);
-
- // boxWidth is the width in residues translated to pixels
- // since the box includes both the start and end residues, add 1 to the
- // difference
- boxWidth = Math
- .round((float) (endRes - startRes + 1) * width / alwidth);
- // boxHeight is the height in sequences translated to pixels
- boxHeight = Math.round((float) (endSeq - startSeq + 1)
- * sequencesHeight
- / alheight);
- }
-
- /**
* Draw the overview panel's viewport box on a graphics object
*
* @param g
return scrollRow;
}
- // TODO should be removed, when unit test has mock Graphics object available
- // to check boxX/boxY
public int getBoxX()
{
return boxX;
}
- // TODO should be removed, when unit test has mock Graphics object available
- // to check boxX/boxY
public int getBoxY()
{
return boxY;
}
- // TODO should be removed, when unit test has mock Graphics object available
public int getBoxWidth()
{
return boxWidth;
}
- // TODO should be removed, when unit test has mock Graphics object available
public int getBoxHeight()
{
return boxHeight;
}
- public void setWidth(int w)
- {
- width = w;
- }
-
- public void setHeight(int h)
- {
- sequencesHeight = h - graphHeight;
- }
-
public int getWidth()
{
return width;
{
return graphHeight;
}
-}
+
+ public float getPixelsPerCol()
+ {
+ resetAlignmentDims();
+ return (float) width / alwidth;
+ }
+
+ public float getPixelsPerSeq()
+ {
+ resetAlignmentDims();
+ return (float) sequencesHeight / alheight;
+ }
+
+ public void setWidth(int w)
+ {
+ width = w;
+ }
+
+ public void setHeight(int h)
+ {
+ sequencesHeight = h - graphHeight;
+ }
+
+ /**
+ * Update the viewport location from a mouse click in the overview panel
+ *
+ * @param mousex
+ * x location of mouse
+ * @param mousey
+ * y location of mouse
+ * @param hiddenSeqs
+ * the alignment's hidden sequences
+ * @param hiddenCols
+ * the alignment's hidden columns
+ */
+ public abstract void updateViewportFromMouse(int mousex, int mousey,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols);
+
+ /**
+ * Set the overview panel's box position to match the viewport
+ *
+ * @param hiddenSeqs
+ * the alignment's hidden sequences
+ * @param hiddenCols
+ * the alignment's hidden columns
+ */
+ public abstract void setBoxPosition(HiddenSequences hiddenSeqs,
+ HiddenColumns hiddenCols);
+
+ /**
+ * Get the collection of columns used by this overview dimensions object
+ *
+ * @param hiddenCols
+ * the alignment's hidden columns
+ * @return a column collection
+ */
+ public abstract AlignmentColsCollectionI getColumns(AlignmentI al);
+
+ /**
+ * Get the collection of rows used by this overview dimensions object
+ *
+ * @param al
+ * the alignment
+ * @return a row collection
+ */
+ public abstract AlignmentRowsCollectionI getRows(AlignmentI al);
+
+ /**
+ * Updates overview dimensions to account for current alignment dimensions
+ */
+ protected abstract void resetAlignmentDims();
+
+ protected void setBoxPosition(int startRes, int endRes, int startSeq,
+ int endSeq)
+ {
+ resetAlignmentDims();
+
+ // boxX, boxY is the x,y location equivalent to startRes, startSeq
+ boxX = Math.round((float) startRes * width / alwidth);
+ boxY = Math.round((float) startSeq * sequencesHeight / alheight);
+
+ // boxWidth is the width in residues translated to pixels
+ // since the box includes both the start and end residues, add 1 to the
+ // difference
+ boxWidth = Math
+ .round((float) (endRes - startRes + 1) * width / alwidth);
+ // boxHeight is the height in sequences translated to pixels
+ boxHeight = Math.round((float) (endSeq - startSeq + 1)
+ * sequencesHeight / alheight);
+ }
+}
\ No newline at end of file
--- /dev/null
+package jalview.viewmodel;
+
+import jalview.api.AlignmentColsCollectionI;
+import jalview.api.AlignmentRowsCollectionI;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.HiddenSequences;
+import jalview.datamodel.VisibleColsCollection;
+import jalview.datamodel.VisibleRowsCollection;
+
+public class OverviewDimensionsHideHidden extends OverviewDimensions
+{
+ private ViewportRanges ranges;
+
+ public OverviewDimensionsHideHidden(ViewportRanges vpranges,
+ boolean showAnnotationPanel)
+ {
+ super(vpranges, showAnnotationPanel);
+ ranges = vpranges;
+ resetAlignmentDims();
+ }
+
+ @Override
+ public void updateViewportFromMouse(int mousex, int mousey,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
+ {
+ resetAlignmentDims();
+
+ int x = mousex;
+ int y = mousey;
+
+ if (x < 0)
+ {
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ y = 0;
+ }
+
+ //
+ // Convert x value to residue position
+ //
+
+ // need to determine where scrollCol should be, given x
+ // to do this also need to know width of viewport, and some hidden column
+ // correction
+
+ // convert x to residues - this is an absolute position
+ int xAsRes = Math.round((float) x * alwidth / width);
+
+ // get viewport width in residues
+ int vpwidth = ranges.getEndRes() - ranges.getStartRes() + 1;
+
+ if (xAsRes + vpwidth > alwidth)
+ {
+ // went past the end of the alignment, adjust backwards
+
+ // if last position was before the end of the alignment, need to update
+ if ((scrollCol + vpwidth - 1) < alwidth)
+ {
+ xAsRes = alwidth - vpwidth;
+ }
+ else
+ {
+ xAsRes = scrollCol;
+ }
+ }
+
+
+ //
+ // Convert y value to sequence position
+ //
+
+ // convert y to residues
+ int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
+
+ // get viewport height in sequences
+ // add 1 because height includes both endSeq and startSeq
+ int vpheight = ranges.getEndSeq() - ranges.getStartSeq() + 1;
+
+ if (yAsSeq + vpheight > alheight)
+ {
+ // went past the end of the alignment, adjust backwards
+ if ((scrollRow + vpheight - 1) < alheight)
+ {
+ yAsSeq = alheight - vpheight;
+ }
+ else
+ {
+ yAsSeq = scrollRow;
+ }
+ }
+
+ // update scroll values
+ scrollCol = xAsRes;
+ scrollRow = yAsSeq;
+
+ }
+
+ @Override
+ public void setBoxPosition(HiddenSequences hiddenSeqs,
+ HiddenColumns hiddenCols)
+ {
+ // work with visible values of startRes and endRes
+ int startRes = ranges.getStartRes();
+ int endRes = ranges.getEndRes();
+
+ // work with visible values of startSeq and endSeq
+ int startSeq = ranges.getStartSeq();
+ int endSeq = ranges.getEndSeq();
+
+ setBoxPosition(startRes, endRes, startSeq, endSeq);
+ }
+
+ @Override
+ public AlignmentColsCollectionI getColumns(AlignmentI al)
+ {
+ return new VisibleColsCollection(0,
+ ranges.getAbsoluteAlignmentWidth() - 1, al);
+ }
+
+ @Override
+ public AlignmentRowsCollectionI getRows(AlignmentI al)
+ {
+ return new VisibleRowsCollection(0,
+ ranges.getAbsoluteAlignmentHeight() - 1, al);
+ }
+
+ @Override
+ protected void resetAlignmentDims()
+ {
+ alwidth = ranges.getVisibleAlignmentWidth();
+ alheight = ranges.getVisibleAlignmentHeight();
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.viewmodel;
+
+import jalview.api.AlignmentColsCollectionI;
+import jalview.api.AlignmentRowsCollectionI;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AllColsCollection;
+import jalview.datamodel.AllRowsCollection;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.HiddenSequences;
+
+public class OverviewDimensionsShowHidden extends OverviewDimensions
+{
+ private ViewportRanges ranges;
+
+ /**
+ * Create an OverviewDimensions object
+ *
+ * @param ranges
+ * positional properties of the viewport
+ * @param showAnnotationPanel
+ * true if the annotation panel is to be shown, false otherwise
+ */
+ public OverviewDimensionsShowHidden(ViewportRanges vpranges,
+ boolean showAnnotationPanel)
+ {
+ super(vpranges, showAnnotationPanel);
+ ranges = vpranges;
+ resetAlignmentDims();
+ }
+
+ /**
+ * Check box dimensions and scroll positions and correct if necessary
+ *
+ * @param mousex
+ * x position in overview panel
+ * @param mousey
+ * y position in overview panel
+ * @param hiddenSeqs
+ * hidden sequences
+ * @param hiddenCols
+ * hidden columns
+ * @param ranges
+ * viewport position properties
+ */
+ @Override
+ public void updateViewportFromMouse(int mousex, int mousey,
+ HiddenSequences hiddenSeqs, HiddenColumns hiddenCols)
+ {
+ int x = mousex;
+ int y = mousey;
+
+ resetAlignmentDims();
+
+ if (x < 0)
+ {
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ y = 0;
+ }
+
+ //
+ // Convert x value to residue position
+ //
+
+ // need to determine where scrollCol should be, given x
+ // to do this also need to know width of viewport, and some hidden column
+ // correction
+
+ // convert x to residues - this is an absolute position
+ int xAsRes = Math.round((float) x * alwidth / width);
+
+ // get viewport width in residues
+ int vpwidth = ranges.getEndRes() - ranges.getStartRes() + 1;
+
+ // get where x should be when accounting for hidden cols
+ // if x is in a hidden col region, shift to left - but we still need
+ // absolute position
+ // so convert back after getting visible region position
+ int visXAsRes = hiddenCols.findColumnPosition(xAsRes);
+
+ // check in case we went off the edge of the alignment
+ int visAlignWidth = hiddenCols.findColumnPosition(alwidth - 1);
+ if (visXAsRes + vpwidth - 1 > visAlignWidth)
+ {
+ // went past the end of the alignment, adjust backwards
+
+ // if last position was before the end of the alignment, need to update
+ if ((scrollCol + vpwidth - 1) < visAlignWidth)
+ {
+ visXAsRes = hiddenCols.findColumnPosition(hiddenCols
+ .subtractVisibleColumns(vpwidth - 1, alwidth - 1));
+ }
+ else
+ {
+ visXAsRes = scrollCol;
+ }
+ }
+
+ //
+ // Convert y value to sequence position
+ //
+
+ // convert y to residues
+ int yAsSeq = Math.round((float) y * alheight / sequencesHeight);
+
+ // get viewport height in sequences
+ // add 1 because height includes both endSeq and startSeq
+ int vpheight = ranges.getEndSeq() - ranges.getStartSeq() + 1;
+
+ // get where y should be when accounting for hidden rows
+ // if y is in a hidden row region, shift up - but we still need absolute
+ // position,
+ // so convert back after getting visible region position
+ yAsSeq = hiddenSeqs.adjustForHiddenSeqs(hiddenSeqs
+ .findIndexWithoutHiddenSeqs(yAsSeq));
+
+ // check in case we went off the edge of the alignment
+ int visAlignHeight = hiddenSeqs.findIndexWithoutHiddenSeqs(alheight);
+ int visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(yAsSeq);
+ if (visYAsSeq + vpheight - 1 > visAlignHeight)
+ {
+ // went past the end of the alignment, adjust backwards
+ if ((scrollRow + vpheight - 1) < visAlignHeight)
+ {
+ visYAsSeq = hiddenSeqs.findIndexWithoutHiddenSeqs(hiddenSeqs
+ .subtractVisibleRows(vpheight - 1, alheight - 1));
+ }
+ else
+ {
+ visYAsSeq = scrollRow;
+ }
+ }
+
+ // update scroll values
+ scrollCol = visXAsRes;
+ scrollRow = visYAsSeq;
+
+ }
+
+ /**
+ * Update the overview panel box when the associated alignment panel is
+ * changed
+ *
+ * @param hiddenSeqs
+ * hidden sequences
+ * @param hiddenCols
+ * hidden columns
+ * @param ranges
+ * viewport position properties
+ */
+ @Override
+ public void setBoxPosition(HiddenSequences hiddenSeqs,
+ HiddenColumns hiddenCols)
+ {
+ // work with absolute values of startRes and endRes
+ int startRes = hiddenCols
+ .adjustForHiddenColumns(ranges.getStartRes());
+ int endRes = hiddenCols.adjustForHiddenColumns(ranges.getEndRes());
+
+ // work with absolute values of startSeq and endSeq
+ int startSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getStartSeq());
+ int endSeq = hiddenSeqs.adjustForHiddenSeqs(ranges.getEndSeq());
+
+ setBoxPosition(startRes, endRes, startSeq, endSeq);
+ }
+
+ @Override
+ public AlignmentColsCollectionI getColumns(AlignmentI al)
+ {
+ return new AllColsCollection(0,
+ ranges.getAbsoluteAlignmentWidth() - 1, al);
+ }
+
+ @Override
+ public AlignmentRowsCollectionI getRows(AlignmentI al)
+ {
+ return new AllRowsCollection(0,
+ ranges.getAbsoluteAlignmentHeight() - 1,
+ al);
+ }
+
+ @Override
+ protected void resetAlignmentDims()
+ {
+ alwidth = ranges.getAbsoluteAlignmentWidth();
+ alheight = ranges.getAbsoluteAlignmentHeight();
+ }
+}
import jalview.analysis.PCA;
import jalview.api.RotatableCanvasI;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
import jalview.datamodel.AlignmentView;
import jalview.datamodel.SequenceI;
import jalview.datamodel.SequencePoint;
public class PCAModel
{
- /*
- * Jalview 2.10.1 treated gaps as X (peptide) or N (nucleotide)
- * for pairwise scoring; 2.10.2 uses gap score (last column) in
- * score matrix (JAL-2397)
- * Set this flag to true (via Groovy) for 2.10.1 behaviour
- */
- private static boolean scoreGapAsAny = false;
-
- public PCAModel(AlignmentView seqstrings2, SequenceI[] seqs2,
- boolean nucleotide2)
- {
- seqstrings = seqstrings2;
- seqs = seqs2;
- nucleotide = nucleotide2;
- score_matrix = nucleotide2 ? "PID" : "BLOSUM62";
- }
-
private volatile PCA pca;
int top;
SequenceI[] seqs;
- /**
- * Score matrix used to calculate PC
+ /*
+ * Name of score model used to calculate PCA
*/
- String score_matrix;
+ ScoreModelI scoreModel;
- /**
- * use the identity matrix for calculating similarity between sequences.
- */
private boolean nucleotide = false;
private Vector<SequencePoint> points;
- private boolean jvCalcMode = true;
+ private SimilarityParamsI similarityParams;
- public boolean isJvCalcMode()
+ /**
+ * Constructor given sequence data, score model and score calculation
+ * parameter options.
+ *
+ * @param seqData
+ * @param sqs
+ * @param nuc
+ * @param modelName
+ * @param params
+ */
+ public PCAModel(AlignmentView seqData, SequenceI[] sqs, boolean nuc,
+ ScoreModelI modelName,
+ SimilarityParamsI params)
{
- return jvCalcMode;
+ seqstrings = seqData;
+ seqs = sqs;
+ nucleotide = nuc;
+ scoreModel = modelName;
+ similarityParams = params;
}
public void run()
{
- char gapChar = scoreGapAsAny ? (nucleotide ? 'N' : 'X') : ' ';
- String[] sequenceStrings = seqstrings.getSequenceStrings(gapChar);
- pca = new PCA(sequenceStrings, nucleotide,
- score_matrix);
- pca.setJvCalcMode(jvCalcMode);
+ pca = new PCA(seqstrings, scoreModel, similarityParams);
pca.run();
// Now find the component coordinates
return pts;
}
- public void setJvCalcMode(boolean state)
- {
- jvCalcMode = state;
- }
-
- public String getScore_matrix()
+ public String getScoreModelName()
{
- return score_matrix;
+ return scoreModel == null ? "" : scoreModel.getName();
}
- public void setScore_matrix(String score_matrix)
+ public void setScoreModel(ScoreModelI sm)
{
- this.score_matrix = score_matrix;
+ this.scoreModel = sm;
}
}
}
/**
+ * Get alignment width in cols, excluding hidden cols
+ */
+ public int getVisibleAlignmentWidth()
+ {
+ return al.getWidth() - al.getHiddenColumns().getSize();
+ }
+
+ /**
+ * Get alignment height in rows, excluding hidden rows
+ */
+ public int getVisibleAlignmentHeight()
+ {
+ return al.getHeight();
+ }
+
+ /**
* Set first residue visible in the viewport
*
* @param res
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
{
minmax = new Hashtable<String, float[][]>();
}
+
+ Set<String> oldGroups = new HashSet<String>(featureGroups.keySet());
AlignmentI alignment = av.getAlignment();
for (int i = 0; i < alignment.getHeight(); i++)
{
int index = 0;
while (index < features.length)
{
+ String fgrp = features[index].getFeatureGroup();
+ oldGroups.remove(fgrp);
if (!featuresDisplayed.isRegistered(features[index].getType()))
{
- String fgrp = features[index].getFeatureGroup();
if (fgrp != null)
{
Boolean groupDisplayed = featureGroups.get(fgrp);
index++;
}
}
+
+ /*
+ * oldGroups now consists of groups that no longer
+ * have any feature in them - remove these
+ */
+ for (String grp : oldGroups)
+ {
+ featureGroups.remove(grp);
+ }
+
updateRenderOrder(allfeatures);
findingFeatures = false;
}
*/
private boolean scaleProteinAsCdna = true;
+ /*
+ * if true, font changes to protein or cDNA are applied to both
+ * sides of a split screen
+ */
+ private boolean proteinFontAsCdna = true;
+
/**
* Copy constructor
*
setScaleAboveWrapped(vs.getScaleAboveWrapped());
setScaleLeftWrapped(vs.getScaleLeftWrapped());
setScaleProteinAsCdna(vs.isScaleProteinAsCdna());
+ setProteinFontAsCdna(vs.isProteinFontAsCdna());
setScaleRightWrapped(vs.getScaleRightWrapped());
setSeqNameItalics(vs.isSeqNameItalics());
setShowAnnotation(vs.isShowAnnotation());
&& getScaleAboveWrapped() == vs.getScaleAboveWrapped()
&& getScaleLeftWrapped() == vs.getScaleLeftWrapped()
&& isScaleProteinAsCdna() == vs.isScaleProteinAsCdna()
+ && isProteinFontAsCdna() == vs.isProteinFontAsCdna()
&& getScaleRightWrapped() == vs.getScaleRightWrapped()
&& isSeqNameItalics() == vs.isSeqNameItalics()
&& isShowAnnotation() == vs.isShowAnnotation()
{
this.scaleProteinAsCdna = b;
}
+
+ @Override
+ public boolean isProteinFontAsCdna()
+ {
+ return proteinFontAsCdna;
+ }
+
+ @Override
+ public void setProteinFontAsCdna(boolean b)
+ {
+ proteinFontAsCdna = b;
+ }
}
* @param counter
* provider of feature counts per alignment position
*/
- public static void newCalculator(FeatureCounterI counter)
+ public static void newCalculator(FeatureSetCounterI counter)
{
- // TODO need an interface for AlignFrame by which to access
- // its AlignViewportI and AlignmentViewPanel
AlignmentViewPanel currentAlignFrame = Jalview.getCurrentAlignFrame().alignPanel;
- if (currentAlignFrame != null)
- {
- newCalculator(currentAlignFrame.getAlignViewport(),
- currentAlignFrame, counter);
- }
- else
+ if (currentAlignFrame == null)
{
System.err
.println("Can't register calculator as no alignment window has focus");
+ return;
}
- }
-
- /**
- * Constructs and registers a new alignment annotation worker
- *
- * @param viewport
- * @param panel
- * @param counter
- * provider of feature counts per alignment position
- */
- public static void newCalculator(AlignViewportI viewport,
- AlignmentViewPanel panel, FeatureCounterI counter)
- {
- new ColumnCounterWorker(viewport, panel, counter);
+ new ColumnCounterSetWorker(currentAlignFrame.getAlignViewport(),
+ currentAlignFrame, counter);
}
/**
AlignFrame currentAlignFrame = Jalview.getCurrentAlignFrame();
if (currentAlignFrame != null)
{
- newCalculator(currentAlignFrame.getViewport(), currentAlignFrame
- .getAlignPanels().get(0), calculator);
+ new AnnotationWorker(currentAlignFrame.getViewport(),
+ currentAlignFrame.getAlignPanels().get(0), calculator);
}
else
{
import java.util.List;
/**
- * A class to compute an alignment annotation with column counts of any
- * properties of interest of positions in an alignment. <br>
+ * A class to compute alignment annotations with column counts for a set of
+ * properties of interest on positions in an alignment. <br>
* This is designed to be extensible, by supplying to the constructor an object
- * that computes a count for each residue position, based on the residue value
- * and any sequence features at that position.
+ * that computes a vector of counts for each residue position, based on the
+ * residue and and sequence features at that position.
*
*/
-class ColumnCounterWorker extends AlignCalcWorker
+class ColumnCounterSetWorker extends AlignCalcWorker
{
- FeatureCounterI counter;
+ FeatureSetCounterI counter;
/**
* Constructor registers the annotation for the given alignment frame
* @param af
* @param counter
*/
- public ColumnCounterWorker(AlignViewportI viewport,
- AlignmentViewPanel panel, FeatureCounterI counter)
+ public ColumnCounterSetWorker(AlignViewportI viewport,
+ AlignmentViewPanel panel, FeatureSetCounterI counter)
{
super(viewport, panel);
ourAnnots = new ArrayList<AlignmentAnnotation>();
@Override
public void run()
{
+ boolean annotationAdded = false;
try
{
calcMan.notifyStart(this);
{
try
{
- computeAnnotations();
+ annotationAdded = computeAnnotations();
} catch (IndexOutOfBoundsException x)
{
// probable race condition. just finish and return without any fuss.
if (ap != null)
{
- ap.adjustAnnotationHeight();
+ if (annotationAdded)
+ {
+ ap.adjustAnnotationHeight();
+ }
ap.paintAlignment(true);
}
/**
* Scan each column of the alignment to calculate a count by feature type. Set
* the count as the value of the alignment annotation for that feature type.
+ *
+ * @return
*/
- void computeAnnotations()
+ boolean computeAnnotations()
{
FeatureRenderer fr = new FeatureRenderer(alignViewport);
// TODO use the commented out code once JAL-2075 is fixed
// AlignmentView alignmentView = alignViewport.getAlignmentView(false);
// AlignmentI alignment = alignmentView.getVisibleAlignment(' ');
- // int width = alignmentView.getWidth();
+ int rows = counter.getNames().length;
+
int width = alignment.getWidth();
int height = alignment.getHeight();
- int[] counts = new int[width];
- int max = 0;
+ int[][] counts = new int[width][rows];
+ int max[] = new int[rows];
+ for (int crow = 0; crow < rows; crow++)
+ {
+ max[crow] = 0;
+ }
+
+ int[] minC = counter.getMinColour();
+ int[] maxC = counter.getMaxColour();
+ Color minColour = new Color(minC[0], minC[1], minC[2]);
+ Color maxColour = new Color(maxC[0], maxC[1], maxC[2]);
for (int col = 0; col < width; col++)
{
- int count = 0;
+ int[] count = counts[col];
+ for (int crow = 0; crow < rows; crow++)
+ {
+ count[crow] = 0;
+ }
for (int row = 0; row < height; row++)
{
- count += countFeaturesAt(alignment, col, row, fr);
+ int[] colcount = countFeaturesAt(alignment, col, row, fr);
+ if (colcount != null)
+ {
+ for (int crow = 0; crow < rows; crow++)
+ {
+ count[crow] += colcount[crow];
+ }
+ }
}
counts[col] = count;
- max = Math.max(count, max);
+ for (int crow = 0; crow < rows; crow++)
+ {
+ max[crow] = Math.max(count[crow], max[crow]);
+ }
}
- Annotation[] anns = new Annotation[width];
- /*
- * add non-zero counts as annotations
- */
- for (int i = 0; i < counts.length; i++)
+ boolean annotationAdded = false;
+
+ for (int anrow = 0; anrow < rows; anrow++)
{
- int count = counts[i];
- if (count > 0)
+ Annotation[] anns = new Annotation[width];
+ /*
+ * add non-zero counts as annotations
+ */
+ for (int i = 0; i < counts.length; i++)
{
- Color color = ColorUtils.getGraduatedColour(count, 0, Color.cyan,
- max, Color.blue);
- String str = String.valueOf(count);
- anns[i] = new Annotation(str, str, '0', count, color);
+ int count = counts[i][anrow];
+ if (count > 0)
+ {
+ Color color = ColorUtils.getGraduatedColour(count, 0, minColour,
+ max[anrow], maxColour);
+ String str = String.valueOf(count);
+ anns[i] = new Annotation(str, str, '0', count, color);
+ }
}
- }
- /*
- * construct or update the annotation
- */
- AlignmentAnnotation ann = alignViewport.getAlignment()
- .findOrCreateAnnotation(counter.getName(),
- counter.getDescription(), false, null, null);
- ann.description = counter.getDescription();
- ann.showAllColLabels = true;
- ann.scaleColLabel = true;
- ann.graph = AlignmentAnnotation.BAR_GRAPH;
- ann.annotations = anns;
- setGraphMinMax(ann, anns);
- ann.validateRangeAndDisplay();
- if (!ourAnnots.contains(ann))
- {
- ourAnnots.add(ann);
+ /*
+ * construct or update the annotation
+ */
+ String description = counter.getDescriptions()[anrow];
+ if (!alignment.findAnnotation(description).iterator().hasNext())
+ {
+ annotationAdded = true;
+ }
+ AlignmentAnnotation ann = alignment.findOrCreateAnnotation(
+ counter.getNames()[anrow], description, false, null, null);
+ ann.description = description;
+ ann.showAllColLabels = true;
+ ann.scaleColLabel = true;
+ ann.graph = AlignmentAnnotation.BAR_GRAPH;
+ ann.annotations = anns;
+ setGraphMinMax(ann, anns);
+ ann.validateRangeAndDisplay();
+ if (!ourAnnots.contains(ann))
+ {
+ ourAnnots.add(ann);
+ }
}
+ return annotationAdded;
}
/**
* @param row
* @param fr
*/
- int countFeaturesAt(AlignmentI alignment, int col, int row,
+ int[] countFeaturesAt(AlignmentI alignment, int col, int row,
FeatureRenderer fr)
{
SequenceI seq = alignment.getSequenceAt(row);
if (seq == null)
{
- return 0;
+ return null;
}
if (col >= seq.getLength())
{
- return 0;// sequence doesn't extend this far
+ return null;// sequence doesn't extend this far
}
char res = seq.getCharAt(col);
if (Comparison.isGap(res))
{
- return 0;
+ return null;
}
int pos = seq.findPosition(col);
// NB have to adjust pos if using AlignmentView.getVisibleAlignment
// see JAL-2075
List<SequenceFeature> features = fr.findFeaturesAtRes(seq, pos);
- int count = this.counter.count(String.valueOf(res), features);
+ int[] count = this.counter.count(String.valueOf(res), features);
return count;
}
* along with Jalview. If not, see <http://www.gnu.org/licenses/>.
* The Jalview Authors are detailed in the 'AUTHORS' file.
*/
+
package jalview.workers;
import jalview.datamodel.SequenceFeature;
import java.util.List;
/**
- * An interface for a type that returns counts of any value of interest at a
- * sequence position that can be determined from the sequence character and any
- * features present at that position
+ * An interface for a type that returns counts (per computed annotation type) of
+ * any value of interest at a sequence position that can be determined from the
+ * sequence character and any features present at that position
*
*/
-public interface FeatureCounterI
+public interface FeatureSetCounterI
{
/**
- * Returns a count of some property of interest, for example
+ * Returns counts (per annotation type) of some properties of interest, for
+ * example
* <ul>
* <li>the number of variant features at the position</li>
* <li>the number of Cath features of status 'True Positive'</li>
* @param a
* list of any sequence features which include the position
*/
- int count(String residue, List<SequenceFeature> features);
+ int[] count(String residue, List<SequenceFeature> features);
/**
- * Returns a name for the annotation that this is counting, for use as the
- * displayed label
+ * Returns names for the annotations that this is counting, for use as the
+ * displayed labels
*
* @return
*/
- String getName();
+ String[] getNames();
/**
- * Returns a description for the annotation, for display as a tooltip
+ * Returns descriptions for the annotations, for display as tooltips
*
* @return
*/
- String getDescription();
+ String[] getDescriptions();
/**
* Returns the colour (as [red, green, blue] values in the range 0-255) to use
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentView;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
import jalview.gui.Desktop;
return null;
}
AlignmentI al = null;
- ColumnSelection alcsel = null;
+ HiddenColumns alhidden = null;
int FirstSeq = -1; // the position of the query sequence in Alignment al
JpredResult result = (JpredResult) this.result;
if (predMap != null)
{
Object[] alandcolsel = input
- .getAlignmentAndColumnSelection(getGapChar());
+ .getAlignmentAndHiddenColumns(getGapChar());
sqs = (SequenceI[]) alandcolsel[0];
al = new Alignment(sqs);
- alcsel = (ColumnSelection) alandcolsel[1];
+ alhidden = (HiddenColumns) alandcolsel[1];
}
else
{
{
char gc = getGapChar();
SequenceI[] sqs = (SequenceI[]) input
- .getAlignmentAndColumnSelection(gc)[0];
+ .getAlignmentAndHiddenColumns(gc)[0];
if (this.msaIndex >= sqs.length)
{
throw new Error(
{
// Adjust input view for gaps
// propagate insertions into profile
- alcsel = ColumnSelection.propagateInsertions(profileseq, al,
+ alhidden = HiddenColumns.propagateInsertions(profileseq, al,
input);
}
}
alant.sequenceRef);
}
}
- return new Object[] { al, alcsel }; // , FirstSeq, noMsa};
+ return new Object[] { al, alhidden }; // , FirstSeq, noMsa};
}
/**
if (res[1] != null)
{
af = new AlignFrame((Alignment) res[0],
- (ColumnSelection) res[1], AlignFrame.DEFAULT_WIDTH,
+ (HiddenColumns) res[1], AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
}
else
*/
af = new AlignFrame((Alignment) res[0],
- (ColumnSelection) res[1], AlignFrame.DEFAULT_WIDTH,
+ (HiddenColumns) res[1],
+ AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
}
Desktop.addInternalFrame(af, altitle, AlignFrame.DEFAULT_WIDTH,
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.AlignmentView;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
import jalview.gui.Desktop;
orders[j] = null;
}
SequenceI[] alignment = (SequenceI[]) newview[0];
- ColumnSelection columnselection = (ColumnSelection) newview[1];
+ HiddenColumns hidden = (HiddenColumns) newview[1];
Alignment al = new Alignment(alignment);
// TODO: add 'provenance' property to alignment from the method notes
// accompanying each subjob
if (newFrame)
{
- AlignFrame af = new AlignFrame(al, columnselection,
+ AlignFrame af = new AlignFrame(al, hidden,
AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
// initialise with same renderer settings as in parent alignframe.
AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
if (nf != null)
{
- af.ShowNewickTree(nf, MessageManager.formatMessage(
+ af.showNewickTree(nf, MessageManager.formatMessage(
"label.tree_from", new String[] { this.alTitle }));
}
// initialise with same renderer settings as in parent alignframe.
/*
* the .jalview_properties entry for JWS2 URLS
*/
- final static String JWS2HOSTURLS = "JWS2HOSTURLS";
+ private final static String JWS2HOSTURLS = "JWS2HOSTURLS";
/*
* Singleton instance
private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
this);
- Vector<String> invalidServiceUrls = null, urlsWithoutServices = null,
- validServiceUrls = null;
+ private Vector<String> invalidServiceUrls = null;
- boolean running = false, aborted = false;
+ private Vector<String> urlsWithoutServices = null;
- Thread oldthread = null;
+ private Vector<String> validServiceUrls = null;
+
+ private volatile boolean running = false;
+
+ private volatile boolean aborted = false;
+
+ private Thread oldthread = null;
/**
* holds list of services.
public void setAborted(boolean aborted)
{
this.aborted = aborted;
-
}
+ @Override
public void run()
{
{
}
}
+ aborted = false;
Cache.log.debug("Old discovery thread has finished.");
}
running = true;
ignoredServices.add(ignored);
}
- changeSupport.firePropertyChange("services", services, new Vector());
+ changeSupport.firePropertyChange("services", services,
+ new Vector<Jws2Instance>());
oldthread = Thread.currentThread();
try
{
if (!aborted)
{
// resort services according to order found in jabaws service list
- // also ensure servics for each host are ordered in same way.
+ // also ensure services for each host are ordered in same way.
if (services != null && services.size() > 0)
{
}
oldthread = null;
running = false;
- changeSupport.firePropertyChange("services", new Vector(), services);
+ changeSupport.firePropertyChange("services",
+ new Vector<Jws2Instance>(), services);
}
/**
service.hasParameters();
if (validServiceUrls == null)
{
- validServiceUrls = new Vector();
+ validServiceUrls = new Vector<String>();
}
validServiceUrls.add(jwsservers);
}
* attach all available web services to the appropriate submenu in the given
* JMenu
*/
+ @Override
public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
{
// dynamically regenerate service list.
{
return;
}
- boolean byhost = Cache.getDefault("WSMENU_BYHOST", false), bytype = Cache
- .getDefault("WSMENU_BYTYPE", false);
+
/**
* eventually, JWS2 services will appear under the same align/etc submenus.
* for moment we keep them separate.
{
new Thread(new Runnable()
{
+ @Override
public void run()
{
setPreferredServiceFor(alignFrame, sv.serviceType,
sv.action, sv);
changeSupport.firePropertyChange("services",
- new Vector(), services);
+ new Vector<Jws2Instance>(), services);
};
}).start();
}
});
}
- /*
- * hitm.addActionListener(new ActionListener() {
- *
- * @Override public void actionPerformed(ActionEvent arg0) { new
- * Thread(new Runnable() {
- *
- * @Override public void run() { new SetPreferredServer(alignFrame,
- * service.serviceType, service.action); } }).start(); } });
- */
}
}
}
* for moment we keep them separate.
*/
JMenu atpoint;
- MsaWSClient msacl = new MsaWSClient();
+
List<String> hostLabels = new ArrayList<String>();
Hashtable<String, String> lasthostFor = new Hashtable<String, String>();
Hashtable<String, ArrayList<Jws2Instance>> hosts = new Hashtable<String, ArrayList<Jws2Instance>>();
new PropertyChangeListener()
{
+ @Override
public void propertyChange(PropertyChangeEvent evt)
{
if (getDiscoverer().services != null)
return true;
}
+ public boolean restart()
+ {
+ synchronized (this)
+ {
+ if (running)
+ {
+ aborted = true;
+ }
+ else
+ {
+ running = true;
+ }
+ return aborted;
+ }
+ }
+
/**
* Start a fresh discovery thread and notify the given object when we're
* finished. Any known existing threads will be killed before this one is
*/
public Thread startDiscoverer(PropertyChangeListener changeSupport2)
{
+ /* if (restart())
+ {
+ return;
+ }
+ else
+ {
+ Thread thr = new Thread(this);
+ thr.start();
+ }
+ */
if (isRunning())
{
setAborted(true);
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.AlignmentView;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
orders[j] = null;
}
SequenceI[] alignment = (SequenceI[]) newview[0];
- ColumnSelection columnselection = (ColumnSelection) newview[1];
+ HiddenColumns hidden = (HiddenColumns) newview[1];
Alignment al = new Alignment(alignment);
// TODO: add 'provenance' property to alignment from the method notes
if (lastProgram != null)
if (newFrame)
{
- displayInNewFrame(al, alorders, columnselection);
+ displayInNewFrame(al, alorders, hidden);
}
else
* @param columnselection
*/
protected void displayInNewFrame(AlignmentI al,
- List<AlignmentOrder> alorders, ColumnSelection columnselection)
+ List<AlignmentOrder> alorders, HiddenColumns hidden)
{
- AlignFrame af = new AlignFrame(al, columnselection,
+ AlignFrame af = new AlignFrame(al, hidden,
AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
// initialise with same renderer settings as in parent alignframe.
{
// intersect groups with selected region
_input = new AlignmentView(av.getAlignment(),
- av.getColumnSelection(), av.getSelectionGroup(),
+ av.getAlignment()
+ .getHiddenColumns(), av.getSelectionGroup(),
av.hasHiddenColumns(), true, true);
viewTitle = MessageManager.formatMessage(
"label.select_visible_region_of",
{
// use selected region to partition alignment
_input = new AlignmentView(av.getAlignment(),
- av.getColumnSelection(), av.getSelectionGroup(),
+ av.getAlignment()
+ .getHiddenColumns(), av.getSelectionGroup(),
av.hasHiddenColumns(), false, true);
}
viewTitle = MessageManager.formatMessage(
{
// just take selected region intersection
_input = new AlignmentView(av.getAlignment(),
- av.getColumnSelection(), av.getSelectionGroup(),
+ av.getAlignment()
+ .getHiddenColumns(), av.getSelectionGroup(),
av.hasHiddenColumns(), true, true);
viewTitle = MessageManager.formatMessage(
"label.select_visible_region_of",
{
// standard alignment view without selection present
_input = new AlignmentView(av.getAlignment(),
- av.getColumnSelection(), null, av.hasHiddenColumns(), false,
+ av.getAlignment()
+ .getHiddenColumns(), null, av.hasHiddenColumns(), false,
true);
viewTitle = ""
+ (av.hasHiddenColumns() ? (new StringBuffer(" ")
import jalview.datamodel.AlignmentI;
import jalview.datamodel.AlignmentOrder;
import jalview.datamodel.Annotation;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
private String getStage(Stage stg)
{
if (stg == Stage.SUBMIT)
+ {
return "submitting ";
+ }
if (stg == Stage.POLL)
+ {
return "checking status of ";
+ }
return (" being confused about ");
}
// total number of distinct alignment sets generated by job set.
int numAlSets = 0, als = 0;
List<AlignmentI> destAls = new ArrayList<AlignmentI>();
- List<jalview.datamodel.ColumnSelection> destColsel = new ArrayList<jalview.datamodel.ColumnSelection>();
+ List<jalview.datamodel.HiddenColumns> destColsel = new ArrayList<jalview.datamodel.HiddenColumns>();
List<List<NewickFile>> trees = new ArrayList<List<NewickFile>>();
do
RestJob rj = (RestJob) jobs[nrj];
int contigs[] = input.getVisibleContigs();
AlignmentI destAl = null;
- jalview.datamodel.ColumnSelection destCs = null;
+ jalview.datamodel.HiddenColumns destHCs = null;
// Resolve destAl for this data.
if (als == 0 && rj.isInputContextModified())
{
if (!restClient.isAlignmentModified() && merge)
{
destAl = restClient.av.getAlignment();
- destCs = restClient.av.getColumnSelection();
+ destHCs = restClient.av.getAlignment().getHiddenColumns();
resultDest
.add(restClient.isShowResultsInNewView() ? AddDataTo.newView
: AddDataTo.currentView);
newAlignment = true;
// recreate the input alignment data
Object[] idat = input
- .getAlignmentAndColumnSelection(gapCharacter);
+ .getAlignmentAndHiddenColumns(gapCharacter);
destAl = new Alignment((SequenceI[]) idat[0]);
- destCs = (ColumnSelection) idat[1];
+ destHCs = (HiddenColumns) idat[1];
resultDest.add(AddDataTo.newAlignment);
// but do not add to the alignment panel list - since we need to
// create a whole new alignFrame set.
}
destAls.add(destAl);
- destColsel.add(destCs);
+ destColsel.add(destHCs);
}
}
else
// recover reference to last alignment created for this rest frame
// ready for extension
destAl = destAls.get(als);
- destCs = destColsel.get(als);
+ destHCs = destColsel.get(als);
}
else
{
newview = input.getUpdatedView(rseqs, orders, gapCharacter);
}
destAl = new Alignment((SequenceI[]) newview[0]);
- destCs = (ColumnSelection) newview[1];
+ destHCs = (HiddenColumns) newview[1];
newAlignment = true;
// TODO create alignment from result data with propagated
// references.
destAls.add(destAl);
- destColsel.add(destCs);
+ destColsel.add(destHCs);
resultDest.add(AddDataTo.newAlignment);
throw new Error(
MessageManager
for (AddDataTo action : resultDest)
{
AlignmentI destal;
- ColumnSelection destcs;
+ HiddenColumns destcs;
String alTitle = MessageManager.formatMessage(
"label.webservice_job_title_on", new String[] {
restClient.service.details.Action,
package jalview.ws.sifts;
import jalview.analysis.AlignSeq;
+import jalview.analysis.scoremodels.ScoreMatrix;
+import jalview.analysis.scoremodels.ScoreModels;
import jalview.api.DBRefEntryI;
import jalview.api.SiftsClientI;
import jalview.datamodel.DBRefEntry;
.equalsIgnoreCase(seqCoordSys.getName())
&& isAccessionMatched(cRefDb.getDbAccessionId()))
{
- String resNumIndexString = cRefDb.getDbResNum()
- .equalsIgnoreCase("None") ? String.valueOf(UNASSIGNED)
- : cRefDb.getDbResNum();
- try
- {
- currSeqIndex = Integer.valueOf(resNumIndexString);
- } catch (NumberFormatException nfe)
- {
- currSeqIndex = Integer.valueOf(resNumIndexString
- .split("[a-zA-Z]")[0]);
- continue;
- }
+ currSeqIndex = getLeadingIntegerValue(
+ cRefDb.getDbResNum(), UNASSIGNED);
if (pdbRefDb != null)
{
break;// exit loop if pdb and uniprot are already found
}
if (currSeqIndex >= seq.getStart() && currSeqIndex <= seq.getEnd())
{
- int resNum;
- try
- {
- resNum = (pdbRefDb == null) ? Integer.valueOf(residue
- .getDbResNum()) : Integer.valueOf(pdbRefDb
- .getDbResNum());
- } catch (NumberFormatException nfe)
- {
- resNum = (pdbRefDb == null) ? Integer.valueOf(residue
- .getDbResNum()) : Integer.valueOf(pdbRefDb
- .getDbResNum().split("[a-zA-Z]")[0]);
- continue;
- }
+
+ int resNum = (pdbRefDb == null) ? getLeadingIntegerValue(
+ residue.getDbResNum(), UNASSIGNED)
+ : getLeadingIntegerValue(pdbRefDb.getDbResNum(),
+ UNASSIGNED);
if (isResidueObserved(residue)
|| seqCoordSys == CoordinateSys.UNIPROT)
}
/**
+ * Get the leading integer part of a string that begins with an integer.
+ *
+ * @param input
+ * - the string input to process
+ * @param failValue
+ * - value returned if unsuccessful
+ * @return
+ */
+ static int getLeadingIntegerValue(String input, int failValue)
+ {
+ if (input == null)
+ {
+ return failValue;
+ }
+ String[] parts = input.split("(?=\\D)(?<=\\d)");
+ if (parts != null && parts.length > 0 && parts[0].matches("[0-9]+"))
+ {
+ return Integer.valueOf(parts[0]);
+ }
+ return failValue;
+ }
+
+
+ /**
*
* @param chainId
* Target chain to populate mapping of its atom positions.
}
@Override
- public StringBuffer getMappingOutput(MappingOutputPojo mp)
+ public StringBuilder getMappingOutput(MappingOutputPojo mp)
throws SiftsException
{
String seqRes = mp.getSeqResidue();
int nochunks = ((seqRes.length()) / len)
+ ((seqRes.length()) % len > 0 ? 1 : 0);
// output mappings
- StringBuffer output = new StringBuffer();
+ StringBuilder output = new StringBuilder(512);
output.append(NEWLINE);
output.append("Sequence \u27f7 Structure mapping details").append(
NEWLINE);
output.append(String.valueOf(pdbEnd));
output.append(NEWLINE).append(NEWLINE);
+ ScoreMatrix pam250 = ScoreModels.getInstance().getPam250();
int matchedSeqCount = 0;
for (int j = 0; j < nochunks; j++)
{
output.append(NEWLINE);
output.append(new Format("%" + (maxid) + "s").form(" ")).append(" ");
- // Print out the matching chars
+ /*
+ * Print out the match symbols:
+ * | for exact match (ignoring case)
+ * . if PAM250 score is positive
+ * else a space
+ */
for (int i = 0; i < len; i++)
{
try
{
if ((i + (j * len)) < seqRes.length())
{
- boolean sameChar = Comparison.isSameResidue(
- seqRes.charAt(i + (j * len)),
- strRes.charAt(i + (j * len)), false);
- if (sameChar
- && !jalview.util.Comparison.isGap(seqRes.charAt(i
- + (j * len))))
+ char c1 = seqRes.charAt(i + (j * len));
+ char c2 = strRes.charAt(i + (j * len));
+ boolean sameChar = Comparison.isSameResidue(c1, c2, false);
+ if (sameChar && !Comparison.isGap(c1))
{
matchedSeqCount++;
output.append("|");
}
else if (type.equals("pep"))
{
- if (ResidueProperties.getPAM250(seqRes.charAt(i + (j * len)),
- strRes.charAt(i + (j * len))) > 0)
+ if (pam250.getPairwiseScore(c1, c2) > 0)
{
output.append(".");
}
*/
package jalview.analysis;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
+import jalview.datamodel.Sequence;
import jalview.gui.JvOptionPane;
import org.testng.annotations.BeforeClass;
assertNull(AlignSeq.extractGaps(null, "ACG"));
assertNull(AlignSeq.extractGaps("-. ", null));
- assertEquals(" AC-G.T", AlignSeq.extractGaps("", " AC-G.T"));
- assertEquals("AC-G.T", AlignSeq.extractGaps(" ", " AC-G.T"));
- assertEquals("ACG.T", AlignSeq.extractGaps(" -", " AC-G.T"));
- assertEquals("ACGT", AlignSeq.extractGaps(" -.", " AC-G.T ."));
- assertEquals(" ACG.T", AlignSeq.extractGaps("-", " AC-G.T"));
+ assertEquals(AlignSeq.extractGaps("", " AC-G.T"), " AC-G.T");
+ assertEquals(AlignSeq.extractGaps(" ", " AC-G.T"), "AC-G.T");
+ assertEquals(AlignSeq.extractGaps(" -", " AC-G.T"), "ACG.T");
+ assertEquals(AlignSeq.extractGaps(" -.", " AC-G.T ."), "ACGT");
+ assertEquals(AlignSeq.extractGaps("-", " AC-G.T"), " ACG.T");
+ }
+
+ @Test(groups = { "Functional" })
+ public void testIndexEncode_nucleotide()
+ {
+ AlignSeq as = new AlignSeq(new Sequence("s1", "TTAG"), new Sequence(
+ "s2", "ACGT"), AlignSeq.DNA);
+ int[] expected = new int[] { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, -1, -1, 10, -1 };
+ String s = "aAcCgGtTuUiIxXrRyYnN .-?";
+ assertArrayEquals(expected, as.indexEncode(s));
+ }
+
+ @Test(groups = { "Functional" })
+ public void testIndexEncode_peptide()
+ {
+ AlignSeq as = new AlignSeq(new Sequence("s1", "PFY"), new Sequence(
+ "s2", "RQW"), AlignSeq.PEP);
+ int[] expected = new int[] { 0, 0, 1, 1, 2, 2, 21, 21, 22, 22, -1, 23,
+ -1, -1, -1 };
+ String s = "aArRnNzZxX *.-?";
+ assertArrayEquals(expected, as.indexEncode(s));
}
}
--- /dev/null
+package jalview.analysis;
+
+import static org.testng.Assert.assertSame;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+
+import java.util.Arrays;
+import java.util.List;
+
+import junit.extensions.PA;
+
+import org.testng.annotations.Test;
+
+public class AlignmentSorterTest
+{
+ @Test(groups = "Functional")
+ public void testSortByFeature_score()
+ {
+ SequenceI seq1 = new Sequence("Seq1", "ABC--D-EFGHIJ");
+ SequenceI seq2 = new Sequence("Seq2", "ABCDEFGHIJ");
+ SequenceI seq3 = new Sequence("Seq3", "ABCDE-FGHIJ");
+ SequenceI seq4 = new Sequence("Seq4", "ABCDEFGHIJ");
+ SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
+ AlignmentI al = new Alignment(seqs);
+ al.setDataset(null);
+
+ /*
+ * sort with no score features does nothing
+ */
+ PA.setValue(AlignmentSorter.class, "lastSortByFeatureScore", null);
+
+ AlignmentSorter.sortByFeature((String) null, null, 0, al.getWidth(),
+ al,
+ AlignmentSorter.FEATURE_SCORE);
+ assertSame(al.getSequenceAt(0), seq1);
+ assertSame(al.getSequenceAt(1), seq2);
+ assertSame(al.getSequenceAt(2), seq3);
+ assertSame(al.getSequenceAt(3), seq4);
+
+ /*
+ * add score and non-score features
+ * seq1 Cath(2.0) Pfam(4.0) average 3.0
+ * seq2 Cath(2.5) Metal(NaN) average 2.5
+ * seq3 KD(-4), KD(3.0) average -0.5
+ * seq4 Helix(NaN) - should sort as if largest score
+ */
+ seq1.addSequenceFeature(new SequenceFeature("Cath", "", 2, 3, 2.0f,
+ "g1"));
+ seq1.addSequenceFeature(new SequenceFeature("Pfam", "", 4, 5, 4.0f,
+ "g2"));
+ seq2.addSequenceFeature(new SequenceFeature("Cath", "", 2, 3, 2.5f,
+ "g3"));
+ seq2.addSequenceFeature(new SequenceFeature("Metal", "", 2, 3,
+ Float.NaN, "g4"));
+ seq3.addSequenceFeature(new SequenceFeature("kD", "", 2, 3, -4f, "g5"));
+ seq3.addSequenceFeature(new SequenceFeature("kD", "", 5, 6, 3.0f, "g6"));
+ seq4.addSequenceFeature(new SequenceFeature("Helix", "", 2, 3,
+ Float.NaN, "g7"));
+
+ /*
+ * sort by ascending score, no filter on feature type or group
+ * NB sort order for the same feature set (none) gets toggled, so descending
+ */
+ PA.setValue(AlignmentSorter.class, "sortByFeatureScoreAscending", true);
+ AlignmentSorter.sortByFeature((String) null, null, 0, al.getWidth(),
+ al, AlignmentSorter.FEATURE_SCORE);
+ assertSame(al.getSequenceAt(3), seq3); // -0.5
+ assertSame(al.getSequenceAt(2), seq2); // 2.5
+ assertSame(al.getSequenceAt(1), seq1); // 3.0
+ assertSame(al.getSequenceAt(0), seq4); // maximum 'score'
+
+ /*
+ * repeat sort toggles order - now ascending
+ */
+ AlignmentSorter.sortByFeature((String) null, null, 0, al.getWidth(),
+ al, AlignmentSorter.FEATURE_SCORE);
+ assertSame(al.getSequenceAt(0), seq3); // -0.5
+ assertSame(al.getSequenceAt(1), seq2); // 2.5
+ assertSame(al.getSequenceAt(2), seq1); // 3.0
+ assertSame(al.getSequenceAt(3), seq4);
+
+ /*
+ * specify features, excluding Pfam
+ * seq1 average is now 2.0
+ * next sort is ascending (not toggled) as for a different feature set
+ */
+ List<String> types = Arrays.asList(new String[] { "Cath", "kD" });
+ AlignmentSorter.sortByFeature(types, null, 0, al.getWidth(), al,
+ AlignmentSorter.FEATURE_SCORE);
+ assertSame(al.getSequenceAt(0), seq3); // -0.5
+ assertSame(al.getSequenceAt(1), seq1); // 2.0
+ assertSame(al.getSequenceAt(2), seq2); // 2.5
+ assertSame(al.getSequenceAt(3), seq4);
+
+ /*
+ * specify groups, excluding g5 (kD -4 score)
+ * seq3 average is now 3.0
+ * next sort is ascending (not toggled) as for a different group spec
+ */
+ List<String> groups = Arrays.asList(new String[] { "g1", "g2", "g3",
+ "g6" });
+ AlignmentSorter.sortByFeature(types, groups, 0, al.getWidth(), al,
+ AlignmentSorter.FEATURE_SCORE);
+ assertSame(al.getSequenceAt(0), seq1); // 2.0
+ assertSame(al.getSequenceAt(1), seq2); // 2.5
+ assertSame(al.getSequenceAt(2), seq3); // 3.0
+ assertSame(al.getSequenceAt(3), seq4);
+
+ /*
+ * limit to columns 0-4, excluding 2nd feature of seq1 and seq3
+ * seq1 is now 2.0, seq3 is now -4
+ */
+ // fails because seq1.findPosition(4) returns 4
+ // although residue 4 is in column 5! - JAL-2544
+ AlignmentSorter.sortByFeature((String) null, null, 0, 4, al,
+ AlignmentSorter.FEATURE_SCORE);
+ assertSame(al.getSequenceAt(0), seq3); // -4
+ assertSame(al.getSequenceAt(1), seq1); // 2.0
+ assertSame(al.getSequenceAt(2), seq2); // 2.5
+ assertSame(al.getSequenceAt(3), seq4);
+ }
+
+ @Test(groups = "Functional")
+ public void testSortByFeature_density()
+ {
+ // TODO
+ }
+}
import jalview.datamodel.AlignedCodon;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignViewport;
AlignmentI alf = new FormatAdapter().readFile(
JAL_1312_example_align_fasta, DataSourceType.PASTE,
FileFormat.Fasta);
- ColumnSelection cs = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
AlignViewportI av = new AlignViewport(alf, cs);
Dna dna = new Dna(av, new int[] { 0, alf.getWidth() - 1 });
AlignmentI translated = dna.translateCdna();
int vwidth = 15;
for (int ipos = 0; ipos + vwidth < alf.getWidth(); ipos += vwidth)
{
- ColumnSelection cs = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
if (ipos > 0)
{
cs.hideColumns(0, ipos - 1);
{
AlignmentI alf = new FormatAdapter().readFile(fasta,
DataSourceType.PASTE, FileFormat.Fasta);
- ColumnSelection cs = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
AlignViewportI av = new AlignViewport(alf, cs);
Dna dna = new Dna(av, new int[] { 0, alf.getWidth() - 1 });
AlignmentI translated = dna.translateCdna();
{
AlignmentI alf = new FormatAdapter().readFile(fasta,
DataSourceType.PASTE, FileFormat.Fasta);
- ColumnSelection cs = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
cs.hideColumns(6, 14); // hide codons 3/4/5
cs.hideColumns(24, 35); // hide codons 9-12
cs.hideColumns(177, 191); // hide codons 60-64
*/
AlignmentI cdna = new AlignmentGenerator(true)
.generate(12, 8, 97, 5, 5);
- ColumnSelection cs = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
AlignViewportI av = new AlignViewport(cdna, cs);
Dna dna = new Dna(av, new int[] { 0, cdna.getWidth() - 1 });
AlignmentI translated = dna.translateCdna();
assertEquals(seqDs, al.getSequenceAt(0).getDatasetSequence()
.getSequenceAsString());
- ColumnSelection cs = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
AlignViewportI av = new AlignViewport(al, cs);
Dna testee = new Dna(av, new int[] { 0, al.getWidth() - 1 });
AlignmentI reversed = testee.reverseCdna(false);
};
as.printAlignment(ps);
- String expected = "Score = 320\nLength of alignment = 10\nSequence Seq1 : 3 - 18 (Sequence length = 14)\nSequence Seq1 : 1 - 10 (Sequence length = 10)\n\n"
+ String expected = "Score = 320.0\nLength of alignment = 10\nSequence Seq1 : 3 - 18 (Sequence length = 14)\nSequence Seq1 : 1 - 10 (Sequence length = 10)\n\n"
+ "Seq1 SDFAQQQRRR\n"
+ " ||||||| \n"
+ "Seq1 SDFAQQQSSS\n\n" + "Percentage ID = 70.00\n";
*/
package jalview.analysis.scoremodels;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
import jalview.gui.JvOptionPane;
import jalview.io.DataSourceType;
import jalview.io.FileLoader;
+import jalview.math.MatrixI;
import java.util.Arrays;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-public class FeatureScoreModelTest
+public class FeatureDistanceModelTest
{
@BeforeClass(alwaysRun = true)
int[] sf3 = new int[] { -1, -1, -1, -1, -1, -1, 76, 77 };
+ /**
+ * <pre>
+ * Load test alignment and add features to sequences:
+ * FER1_MESCR FER1_SPIOL FER3_RAPSA FER1_MAIZE
+ * sf1 X X X
+ * sf2 X X
+ * sf3 X
+ * </pre>
+ *
+ * @return
+ */
public AlignFrame getTestAlignmentFrame()
{
AlignFrame alf = new FileLoader(false).LoadFileWaitTillLoaded(
alf.getFeatureRenderer().findAllFeatures(true);
Assert.assertEquals(alf.getFeatureRenderer().getDisplayedFeatureTypes()
.size(), 3, "Number of feature types");
- Assert.assertTrue(alf.getCurrentView().areFeaturesDisplayed());
+ assertTrue(alf.getCurrentView().areFeaturesDisplayed());
return alf;
}
public void testFeatureScoreModel() throws Exception
{
AlignFrame alf = getTestAlignmentFrame();
- FeatureScoreModel fsm = new FeatureScoreModel();
- Assert.assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
+ FeatureDistanceModel fsm = new FeatureDistanceModel();
+ assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
.getAlignPanel()));
alf.selectAllSequenceMenuItem_actionPerformed(null);
- float[][] dm = fsm.findDistances(alf.getViewport().getAlignmentView(
- true));
- Assert.assertTrue(dm[0][2] == 0f,
+
+ MatrixI dm = fsm.findDistances(
+ alf.getViewport().getAlignmentView(true),
+ SimilarityParams.Jalview);
+ assertEquals(dm.getValue(0, 2), 0d,
"FER1_MESCR (0) should be identical with RAPSA (2)");
- Assert.assertTrue(dm[0][1] > dm[0][2],
+ assertTrue(dm.getValue(0, 1) > dm.getValue(0, 2),
"FER1_MESCR (0) should be further from SPIOL (1) than it is from RAPSA (2)");
}
AlignFrame alf = getTestAlignmentFrame();
// hiding first two columns shouldn't affect the tree
alf.getViewport().hideColumns(0, 1);
- FeatureScoreModel fsm = new FeatureScoreModel();
- Assert.assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
+ FeatureDistanceModel fsm = new FeatureDistanceModel();
+ assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
.getAlignPanel()));
alf.selectAllSequenceMenuItem_actionPerformed(null);
- float[][] dm = fsm.findDistances(alf.getViewport().getAlignmentView(
- true));
- Assert.assertTrue(dm[0][2] == 0f,
+ MatrixI dm = fsm.findDistances(
+ alf.getViewport().getAlignmentView(true),
+ SimilarityParams.Jalview);
+ assertEquals(dm.getValue(0, 2), 0d,
"FER1_MESCR (0) should be identical with RAPSA (2)");
- Assert.assertTrue(dm[0][1] > dm[0][2],
+ assertTrue(dm.getValue(0, 1) > dm.getValue(0, 2),
"FER1_MESCR (0) should be further from SPIOL (1) than it is from RAPSA (2)");
}
// hide columns and check tree changes
alf.getViewport().hideColumns(3, 4);
alf.getViewport().hideColumns(0, 1);
- FeatureScoreModel fsm = new FeatureScoreModel();
- Assert.assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
+ FeatureDistanceModel fsm = new FeatureDistanceModel();
+ assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
.getAlignPanel()));
alf.selectAllSequenceMenuItem_actionPerformed(null);
- float[][] dm = fsm.findDistances(alf.getViewport().getAlignmentView(
- true));
- Assert.assertTrue(
- dm[0][2] == 0f,
+ MatrixI dm = fsm.findDistances(
+ alf.getViewport().getAlignmentView(true),
+ SimilarityParams.Jalview);
+ assertEquals(
+ dm.getValue(0, 2),
+ 0d,
"After hiding last two columns FER1_MESCR (0) should still be identical with RAPSA (2)");
- Assert.assertTrue(
- dm[0][1] == 0f,
+ assertEquals(
+ dm.getValue(0, 1),
+ 0d,
"After hiding last two columns FER1_MESCR (0) should now also be identical with SPIOL (1)");
for (int s = 0; s < 3; s++)
{
- Assert.assertTrue(dm[s][3] > 0f, "After hiding last two columns "
+ assertTrue(dm.getValue(s, 3) > 0d, "After hiding last two columns "
+ alf.getViewport().getAlignment().getSequenceAt(s).getName()
+ "(" + s + ") should still be distinct from FER1_MAIZE (3)");
}
SequenceFeature sf = null;
sf = new SequenceFeature("disulphide bond", "", 2, 5, Float.NaN, "");
aseq.addSequenceFeature(sf);
- Assert.assertTrue(sf.isContactFeature());
+ assertTrue(sf.isContactFeature());
af.refreshFeatureUI(true);
af.getFeatureRenderer().setAllVisible(Arrays.asList("disulphide bond"));
Assert.assertEquals(af.getFeatureRenderer().getDisplayedFeatureTypes()
.size(), 0);
}
+ @Test(groups = { "Functional" })
+ public void testFindDistances() throws Exception
+ {
+ String seqs = ">s1\nABCDE\n>seq2\nABCDE\n";
+ AlignFrame alf = new FileLoader().LoadFileWaitTillLoaded(seqs,
+ DataSourceType.PASTE);
+ SequenceI s1 = alf.getViewport().getAlignment().getSequenceAt(0);
+ SequenceI s2 = alf.getViewport().getAlignment().getSequenceAt(1);
+
+ /*
+ * set domain and variant features thus:
+ * ----5
+ * s1 ddd..
+ * s1 .vvv.
+ * s1 ..vvv
+ * s2 .ddd.
+ * s2 vv..v
+ * The number of unshared feature types per column is
+ * 20120 (two features of the same type doesn't affect score)
+ * giving an average (pairwise distance) of 5/5 or 1.0
+ */
+ s1.addSequenceFeature(new SequenceFeature("domain", null, 1, 3, 0f,
+ null));
+ s1.addSequenceFeature(new SequenceFeature("variant", null, 2, 4, 0f,
+ null));
+ s1.addSequenceFeature(new SequenceFeature("variant", null, 3, 5, 0f,
+ null));
+ s2.addSequenceFeature(new SequenceFeature("domain", null, 2, 4, 0f,
+ null));
+ s2.addSequenceFeature(new SequenceFeature("variant", null, 1, 2, 0f,
+ null));
+ s2.addSequenceFeature(new SequenceFeature("variant", null, 5, 5, 0f,
+ null));
+ alf.setShowSeqFeatures(true);
+ alf.getFeatureRenderer().findAllFeatures(true);
+
+ FeatureDistanceModel fsm = new FeatureDistanceModel();
+ assertTrue(fsm.configureFromAlignmentView(alf.getCurrentView()
+ .getAlignPanel()));
+ alf.selectAllSequenceMenuItem_actionPerformed(null);
+
+ MatrixI distances = fsm.findDistances(alf.getViewport()
+ .getAlignmentView(true), SimilarityParams.Jalview);
+ assertEquals(distances.width(), 2);
+ assertEquals(distances.height(), 2);
+ assertEquals(distances.getValue(0, 0), 0d);
+ assertEquals(distances.getValue(1, 1), 0d);
+
+ assertEquals(distances.getValue(0, 1), 1d,
+ "expected identical pairs. (check normalisation for similarity score)");
+ assertEquals(distances.getValue(1, 0), 1d);
+ }
+
+ /**
+ * Verify computed distances with varying parameter options
+ */
+ @Test(groups = "Functional")
+ public void testFindDistances_withParams()
+ {
+ AlignFrame af = setupAlignmentView();
+ AlignViewport viewport = af.getViewport();
+ AlignmentView view = viewport.getAlignmentView(false);
+
+ FeatureDistanceModel sm = new FeatureDistanceModel();
+ sm.configureFromAlignmentView(af.alignPanel);
+
+ /*
+ * feature distance model always normalises by region width
+ * gap-gap is always included (but scores zero)
+ * the only variable parameter is 'includeGaps'
+ */
+
+ /*
+ * include gaps
+ * score = 3 + 3 + 0 + 2 + 3 + 2 = 13/6
+ */
+ SimilarityParamsI params = new SimilarityParams(true, true, true, true);
+ MatrixI distances = sm.findDistances(view, params);
+ assertEquals(distances.getValue(0, 0), 0d);
+ assertEquals(distances.getValue(1, 1), 0d);
+ assertEquals(distances.getValue(0, 1), 13d / 6); // should be 13d/6
+ assertEquals(distances.getValue(1, 0), 13d / 6);
+
+ /*
+ * exclude gaps
+ * score = 3 + 3 + 0 + 0 + 0 + 0 = 6/6
+ */
+ params = new SimilarityParams(true, true, false, true);
+ distances = sm.findDistances(view, params);
+ assertEquals(distances.getValue(0, 1), 6d / 6);// should be 6d/6
+ }
+
+ /**
+ * <pre>
+ * Set up
+ * column 1 2 3 4 5 6
+ * seq s1 F R - K - S
+ * seq s2 F S - - L
+ * s1 chain c c c c
+ * s1 domain d d d d
+ * s2 chain c c c
+ * s2 metal m m m
+ * s2 Pfam P P P
+ * scores: 3 3 0 2 3 2
+ * </pre>
+ *
+ * @return
+ */
+ protected AlignFrame setupAlignmentView()
+ {
+ /*
+ * for now, using space for gap to match callers of
+ * AlignmentView.getSequenceStrings()
+ * may change this to '-' (with corresponding change to matrices)
+ */
+ SequenceI s1 = new Sequence("s1", "FR K S");
+ SequenceI s2 = new Sequence("s2", "FS L");
+
+ s1.addSequenceFeature(new SequenceFeature("chain", null, 1, 4, 0f, null));
+ s1.addSequenceFeature(new SequenceFeature("domain", null, 1, 4, 0f,
+ null));
+ s2.addSequenceFeature(new SequenceFeature("chain", null, 1, 3, 0f, null));
+ s2.addSequenceFeature(new SequenceFeature("metal", null, 1, 3, 0f, null));
+ s2.addSequenceFeature(new SequenceFeature("Pfam", null, 1, 3, 0f, null));
+ AlignmentI al = new Alignment(new SequenceI[] { s1, s2 });
+ AlignFrame af = new AlignFrame(al, 300, 300);
+ af.setShowSeqFeatures(true);
+ af.getFeatureRenderer().findAllFeatures(true);
+ return af;
+ }
+
}
--- /dev/null
+package jalview.analysis.scoremodels;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.util.Comparison;
+
+import org.testng.annotations.Test;
+
+public class PIDModelTest
+{
+ private static final double DELTA = 0.00001D;
+
+ @Test(groups = "Functional")
+ public void testGetPairwiseScore()
+ {
+ PIDModel sm = new PIDModel();
+ assertEquals(sm.getPairwiseScore('A', 'A'), 1f);
+ assertEquals(sm.getPairwiseScore('A', 'a'), 1f);
+ assertEquals(sm.getPairwiseScore('a', 'A'), 1f);
+ assertEquals(sm.getPairwiseScore('A', 'B'), 0f);
+ assertEquals(sm.getPairwiseScore('A', ' '), 0f);
+ assertEquals(sm.getPairwiseScore(' ', ' '), 0f);
+ assertEquals(sm.getPairwiseScore('.', '.'), 0f);
+ assertEquals(sm.getPairwiseScore('-', '-'), 0f);
+ }
+
+ /**
+ * Regression test to verify that a (suitably configured) PIDModel computes
+ * the same percentage identities as the Comparison.PID method
+ */
+ @Test(groups = "Functional")
+ public void testComputePID_matchesComparisonPID()
+ {
+ SimilarityParamsI params = new SimilarityParams(true, true, true, true);
+
+ /*
+ * same length, no gaps
+ */
+ String s1 = "ARFNQDWSGI";
+ String s2 = "ARKNQDQSGI";
+
+ new PIDModel();
+ double newScore = PIDModel.computePID(s1, s2, params);
+ double oldScore = Comparison.PID(s1, s2);
+ assertEquals(newScore, oldScore, DELTA);
+
+ /*
+ * same length, with gaps
+ */
+ s1 = "-RFNQDWSGI";
+ s2 = "ARKNQ-QSGI";
+ new PIDModel();
+ newScore = PIDModel.computePID(s1, s2, params);
+ oldScore = Comparison.PID(s1, s2);
+ assertEquals(newScore, oldScore, DELTA);
+
+ /*
+ * s2 longer than s1, with gaps
+ */
+ s1 = "ARK-";
+ s2 = "-RFNQ";
+ new PIDModel();
+ newScore = PIDModel.computePID(s1, s2, params);
+ oldScore = Comparison.PID(s1, s2);
+ assertEquals(newScore, oldScore, DELTA);
+
+ /*
+ * s1 longer than s2, with gaps
+ */
+ s1 = "-RFNQ";
+ s2 = "ARK-";
+ new PIDModel();
+ newScore = PIDModel.computePID(s1, s2, params);
+ oldScore = Comparison.PID(s1, s2);
+ assertEquals(newScore, oldScore, DELTA);
+
+ /*
+ * same but now also with gapped columns
+ */
+ s1 = "-R-F-NQ";
+ s2 = "AR-K--";
+ new PIDModel();
+ newScore = PIDModel.computePID(s1, s2, params);
+ oldScore = Comparison.PID(s1, s2);
+ assertEquals(newScore, oldScore, DELTA);
+ }
+
+ /**
+ * Tests for percentage identity variants where only the shorter length of two
+ * sequences is used
+ */
+ @Test(groups = "Functional")
+ public void testComputePID_matchShortestSequence()
+ {
+ String s1 = "FR-K-S";
+ String s2 = "FS--L";
+
+ /*
+ * match gap-gap and gap-char
+ * PID = 4/5 = 80%
+ */
+ SimilarityParamsI params = new SimilarityParams(true, true, true, true);
+ assertEquals(PIDModel.computePID(s1, s2, params), 80d);
+
+ /*
+ * match gap-char but not gap-gap
+ * PID = 3/4 = 75%
+ */
+ params = new SimilarityParams(false, true, true, true);
+ assertEquals(PIDModel.computePID(s1, s2, params), 75d);
+
+ /*
+ * include gaps but don't match them
+ * include gap-gap, counted as identity
+ * PID = 2/5 = 40%
+ */
+ params = new SimilarityParams(true, false, true, true);
+ assertEquals(PIDModel.computePID(s1, s2, params), 40d);
+
+ /*
+ * include gaps but don't match them
+ * exclude gap-gap
+ * PID = 1/4 = 25%
+ */
+ params = new SimilarityParams(false, false, true, true);
+ assertEquals(PIDModel.computePID(s1, s2, params), 25d);
+ }
+
+ /**
+ * Tests for percentage identity variants where the longer length of two
+ * sequences is used
+ */
+ @Test(groups = "Functional")
+ public void testComputePID_matchLongestSequence()
+ {
+ String s1 = "FR-K-S";
+ String s2 = "FS--L";
+
+ /*
+ * match gap-gap and gap-char
+ * shorter sequence treated as if with trailing gaps
+ * PID = 5/6 = 83.333...%
+ */
+ SimilarityParamsI params = new SimilarityParams(true, true, true, false);
+ assertEquals(PIDModel.computePID(s1, s2, params), 500d / 6);
+
+ /*
+ * match gap-char but not gap-gap
+ * PID = 4/5 = 80%
+ */
+ params = new SimilarityParams(false, true, true, false);
+ assertEquals(PIDModel.computePID(s1, s2, params), 80d);
+
+ /*
+ * include gaps but don't match them
+ * include gap-gap, counted as identity
+ * PID = 2/6 = 33.333...%
+ */
+ params = new SimilarityParams(true, false, true, false);
+ assertEquals(PIDModel.computePID(s1, s2, params), 100d / 3);
+
+ /*
+ * include gaps but don't match them
+ * exclude gap-gap
+ * PID = 1/5 = 25%
+ */
+ params = new SimilarityParams(false, false, true, false);
+ assertEquals(PIDModel.computePID(s1, s2, params), 20d);
+
+ /*
+ * no tests for matchGaps=true, includeGaps=false
+ * as it don't make sense
+ */
+ }
+}
--- /dev/null
+package jalview.analysis.scoremodels;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
+
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.io.DataSourceType;
+import jalview.io.FileParse;
+import jalview.io.ScoreMatrixFile;
+import jalview.math.MatrixI;
+import jalview.schemes.ResidueProperties;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.Arrays;
+
+import org.testng.annotations.Test;
+
+public class ScoreMatrixTest
+{
+ @Test(groups = "Functional")
+ public void testConstructor()
+ {
+ // note score matrix does not have to be symmetric (though it should be!)
+ float[][] scores = new float[3][];
+ scores[0] = new float[] { 1f, 2f, 3f };
+ scores[1] = new float[] { -4f, 5f, 6f };
+ scores[2] = new float[] { 7f, 8f, 9f };
+ ScoreMatrix sm = new ScoreMatrix("Test", "ABC".toCharArray(), scores);
+ assertEquals(sm.getSize(), 3);
+ assertArrayEquals(scores, sm.getMatrix());
+ assertEquals(sm.getPairwiseScore('A', 'a'), 1f);
+ assertEquals(sm.getPairwiseScore('b', 'c'), 6f);
+ assertEquals(sm.getPairwiseScore('c', 'b'), 8f);
+ assertEquals(sm.getMatrixIndex('c'), 2);
+ assertEquals(sm.getMatrixIndex(' '), -1);
+
+ // substitution to or from unknown symbol gets minimum score
+ assertEquals(sm.getPairwiseScore('A', 'D'), -4f);
+ assertEquals(sm.getPairwiseScore('D', 'A'), -4f);
+ // unknown-to-self gets a score of 1
+ assertEquals(sm.getPairwiseScore('D', 'D'), 1f);
+ }
+
+ @Test(
+ groups = "Functional",
+ expectedExceptions = { IllegalArgumentException.class })
+ public void testConstructor_matrixTooSmall()
+ {
+ float[][] scores = new float[2][];
+ scores[0] = new float[] { 1f, 2f };
+ scores[1] = new float[] { 3f, 4f };
+ new ScoreMatrix("Test", "ABC".toCharArray(), scores);
+ }
+
+ @Test(
+ groups = "Functional",
+ expectedExceptions = { IllegalArgumentException.class })
+ public void testConstructor_matrixTooBig()
+ {
+ float[][] scores = new float[2][];
+ scores[0] = new float[] { 1f, 2f };
+ scores[1] = new float[] { 3f, 4f };
+ new ScoreMatrix("Test", "A".toCharArray(), scores);
+ }
+
+ @Test(
+ groups = "Functional",
+ expectedExceptions = { IllegalArgumentException.class })
+ public void testConstructor_matrixNotSquare()
+ {
+ float[][] scores = new float[2][];
+ scores[0] = new float[] { 1f, 2f };
+ scores[1] = new float[] { 3f };
+ new ScoreMatrix("Test", "AB".toCharArray(), scores);
+ }
+
+ @Test(groups = "Functional")
+ public void testBuildSymbolIndex()
+ {
+ float[][] scores = new float[2][];
+ scores[0] = new float[] { 1f, 2f };
+ scores[1] = new float[] { 3f, 4f };
+ ScoreMatrix sm = new ScoreMatrix("Test", new char[] { 'A', '.' },
+ scores);
+ short[] index = sm.buildSymbolIndex("AX-yxYp".toCharArray());
+
+ assertEquals(index.length, 128); // ASCII character set size
+
+ assertEquals(index['A'], 0);
+ assertEquals(index['a'], 0); // lower-case mapping added
+ assertEquals(index['X'], 1);
+ assertEquals(index['-'], 2);
+ assertEquals(index['y'], 3); // lower-case override
+ assertEquals(index['x'], 4); // lower-case override
+ assertEquals(index['Y'], 5);
+ assertEquals(index['p'], 6);
+ assertEquals(index['P'], -1); // lower-case doesn't map upper-case
+
+ /*
+ * check all unmapped symbols have index for unmapped
+ */
+ for (int c = 0; c < index.length; c++)
+ {
+ if (!"AaXx-. Yyp".contains(String.valueOf((char) c)))
+ {
+ assertEquals(index[c], -1);
+ }
+ }
+ }
+
+ /**
+ * check that characters not in the basic ASCII set are simply ignored
+ */
+ @Test(groups = "Functional")
+ public void testBuildSymbolIndex_nonAscii()
+ {
+ float[][] scores = new float[2][];
+ scores[0] = new float[] { 1f, 2f };
+ scores[1] = new float[] { 3f, 4f };
+ ScoreMatrix sm = new ScoreMatrix("Test", new char[] { 'A', '.' },
+ scores);
+ char[] weird = new char[] { 128, 245, 'P' };
+ short[] index = sm.buildSymbolIndex(weird);
+ assertEquals(index.length, 128);
+ assertEquals(index['P'], 2);
+ assertEquals(index['p'], 2);
+ for (int c = 0; c < index.length; c++)
+ {
+ if (c != 'P' && c != 'p')
+ {
+ assertEquals(index[c], -1);
+ }
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testGetMatrix()
+ {
+ ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
+ float[][] m = sm.getMatrix();
+ assertEquals(m.length, sm.getSize());
+ assertEquals(m[2][4], -3f);
+ // verify a defensive copy is returned
+ float[][] m2 = sm.getMatrix();
+ assertNotSame(m, m2);
+ assertTrue(Arrays.deepEquals(m, m2));
+ }
+
+ @Test(groups = "Functional")
+ public void testGetMatrixIndex()
+ {
+ ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
+ assertEquals(sm.getMatrixIndex('A'), 0);
+ assertEquals(sm.getMatrixIndex('R'), 1);
+ assertEquals(sm.getMatrixIndex('r'), 1);
+ assertEquals(sm.getMatrixIndex('N'), 2);
+ assertEquals(sm.getMatrixIndex('D'), 3);
+ assertEquals(sm.getMatrixIndex('X'), 22);
+ assertEquals(sm.getMatrixIndex('x'), 22);
+ assertEquals(sm.getMatrixIndex('-'), -1);
+ assertEquals(sm.getMatrixIndex('*'), 23);
+ assertEquals(sm.getMatrixIndex('.'), -1);
+ assertEquals(sm.getMatrixIndex(' '), -1);
+ assertEquals(sm.getMatrixIndex('?'), -1);
+ assertEquals(sm.getMatrixIndex((char) 128), -1);
+ }
+
+ @Test(groups = "Functional")
+ public void testGetSize()
+ {
+ ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
+ assertEquals(sm.getMatrix().length, sm.getSize());
+ }
+
+ @Test(groups = "Functional")
+ public void testComputePairwiseScores()
+ {
+ /*
+ * NB score matrix expects '-' for gap
+ */
+ String[] seqs = new String[] { "FKL", "R-D", "QIA", "GWC" };
+ ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
+
+ MatrixI pairwise = sm.findSimilarities(seqs, SimilarityParams.Jalview);
+
+ /*
+ * should be NxN where N = number of sequences
+ */
+ assertEquals(pairwise.height(), 4);
+ assertEquals(pairwise.width(), 4);
+
+ /*
+ * should be symmetrical (because BLOSUM62 is)
+ */
+ for (int i = 0; i < pairwise.height(); i++)
+ {
+ for (int j = i + 1; j < pairwise.width(); j++)
+ {
+ assertEquals(pairwise.getValue(i, j), pairwise.getValue(j, i),
+ String.format("Not symmetric at [%d, %d]", i, j));
+ }
+ }
+ /*
+ * verify expected BLOSUM dot product scores
+ */
+ // F.F + K.K + L.L = 6 + 5 + 4 = 15
+ assertEquals(pairwise.getValue(0, 0), 15d);
+ // R.R + -.- + D.D = 5 + 1 + 6 = 12
+ assertEquals(pairwise.getValue(1, 1), 12d);
+ // Q.Q + I.I + A.A = 5 + 4 + 4 = 13
+ assertEquals(pairwise.getValue(2, 2), 13d);
+ // G.G + W.W + C.C = 6 + 11 + 9 = 26
+ assertEquals(pairwise.getValue(3, 3), 26d);
+ // F.R + K.- + L.D = -3 + -4 + -4 = -11
+ assertEquals(pairwise.getValue(0, 1), -11d);
+ // F.Q + K.I + L.A = -3 + -3 + -1 = -7
+ assertEquals(pairwise.getValue(0, 2), -7d);
+ // F.G + K.W + L.C = -3 + -3 + -1 = -7
+ assertEquals(pairwise.getValue(0, 3), -7d);
+ // R.Q + -.I + D.A = 1 + -4 + -2 = -5
+ assertEquals(pairwise.getValue(1, 2), -5d);
+ // R.G + -.W + D.C = -2 + -4 + -3 = -9
+ assertEquals(pairwise.getValue(1, 3), -9d);
+ // Q.G + I.W + A.C = -2 + -3 + 0 = -5
+ assertEquals(pairwise.getValue(2, 3), -5d);
+ }
+
+ /**
+ * Test that the result of outputMatrix can be reparsed to give an identical
+ * ScoreMatrix
+ *
+ * @throws IOException
+ * @throws MalformedURLException
+ */
+ @Test(groups = "Functional")
+ public void testOutputMatrix_roundTrip() throws MalformedURLException,
+ IOException
+ {
+ ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
+ String output = sm.outputMatrix(false);
+ FileParse fp = new FileParse(output, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ ScoreMatrix sm2 = parser.parseMatrix();
+ assertNotNull(sm2);
+ assertTrue(sm2.equals(sm));
+ }
+
+ @Test(groups = "Functional")
+ public void testEqualsAndHashCode()
+ {
+ ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
+ ScoreMatrix sm2 = new ScoreMatrix(sm.getName(), sm.getSymbols()
+ .toCharArray(), sm.getMatrix());
+ assertTrue(sm.equals(sm2));
+ assertEquals(sm.hashCode(), sm2.hashCode());
+
+ sm2 = ScoreModels.getInstance().getPam250();
+ assertFalse(sm.equals(sm2));
+ assertNotEquals(sm.hashCode(), sm2.hashCode());
+
+ assertFalse(sm.equals("hello"));
+ }
+
+ /**
+ * Tests for scoring options where the longer length of two sequences is used
+ */
+ @Test(groups = "Functional")
+ public void testcomputeSimilarity_matchLongestSequence()
+ {
+ /*
+ * ScoreMatrix expects '-' for gaps
+ */
+ String s1 = "FR-K-S";
+ String s2 = "FS--L";
+ ScoreMatrix blosum = ScoreModels.getInstance().getBlosum62();
+
+ /*
+ * score gap-gap and gap-char
+ * shorter sequence treated as if with trailing gaps
+ * score = F^F + R^S + -^- + K^- + -^L + S^-
+ * = 6 + -1 + 1 + -4 + -4 + -4 = -6
+ */
+ SimilarityParamsI params = new SimilarityParams(true, true, true, false);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), -6d);
+ // matchGap (arg2) is ignored:
+ params = new SimilarityParams(true, false, true, false);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), -6d);
+
+ /*
+ * score gap-char but not gap-gap
+ * score = F^F + R^S + 0 + K^- + -^L + S^-
+ * = 6 + -1 + 0 + -4 + -4 + -4 = -7
+ */
+ params = new SimilarityParams(false, true, true, false);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), -7d);
+ // matchGap (arg2) is ignored:
+ params = new SimilarityParams(false, false, true, false);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), -7d);
+
+ /*
+ * score gap-gap but not gap-char
+ * score = F^F + R^S + -^- + 0 + 0 + 0
+ * = 6 + -1 + 1 = 6
+ */
+ params = new SimilarityParams(true, false, false, false);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), 6d);
+ // matchGap (arg2) is ignored:
+ params = new SimilarityParams(true, true, false, false);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), 6d);
+
+ /*
+ * score neither gap-gap nor gap-char
+ * score = F^F + R^S + 0 + 0 + 0 + 0
+ * = 6 + -1 = 5
+ */
+ params = new SimilarityParams(false, false, false, false);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), 5d);
+ // matchGap (arg2) is ignored:
+ params = new SimilarityParams(false, true, false, false);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), 5d);
+ }
+
+ /**
+ * Tests for scoring options where only the shorter length of two sequences is
+ * used
+ */
+ @Test(groups = "Functional")
+ public void testcomputeSimilarity_matchShortestSequence()
+ {
+ /*
+ * ScoreMatrix expects '-' for gaps
+ */
+ String s1 = "FR-K-S";
+ String s2 = "FS--L";
+ ScoreMatrix blosum = ScoreModels.getInstance().getBlosum62();
+
+ /*
+ * score gap-gap and gap-char
+ * match shorter sequence only
+ * score = F^F + R^S + -^- + K^- + -^L
+ * = 6 + -1 + 1 + -4 + -4 = -2
+ */
+ SimilarityParamsI params = new SimilarityParams(true, true, true, true);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), -2d);
+ // matchGap (arg2) is ignored:
+ params = new SimilarityParams(true, false, true, true);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), -2d);
+
+ /*
+ * score gap-char but not gap-gap
+ * score = F^F + R^S + 0 + K^- + -^L
+ * = 6 + -1 + 0 + -4 + -4 = -3
+ */
+ params = new SimilarityParams(false, true, true, true);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), -3d);
+ // matchGap (arg2) is ignored:
+ params = new SimilarityParams(false, false, true, true);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), -3d);
+
+ /*
+ * score gap-gap but not gap-char
+ * score = F^F + R^S + -^- + 0 + 0
+ * = 6 + -1 + 1 = 6
+ */
+ params = new SimilarityParams(true, false, false, true);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), 6d);
+ // matchGap (arg2) is ignored:
+ params = new SimilarityParams(true, true, false, true);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), 6d);
+
+ /*
+ * score neither gap-gap nor gap-char
+ * score = F^F + R^S + 0 + 0 + 0
+ * = 6 + -1 = 5
+ */
+ params = new SimilarityParams(false, false, false, true);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), 5d);
+ // matchGap (arg2) is ignored:
+ params = new SimilarityParams(false, true, false, true);
+ assertEquals(blosum.computeSimilarity(s1, s2, params), 5d);
+ }
+
+ @Test(groups = "Functional")
+ public void testSymmetric()
+ {
+ verifySymmetric(ScoreModels.getInstance().getBlosum62());
+ verifySymmetric(ScoreModels.getInstance().getPam250());
+ verifySymmetric(ScoreModels.getInstance().getDefaultModel(false)); // dna
+ }
+
+ private void verifySymmetric(ScoreMatrix sm)
+ {
+ float[][] m = sm.getMatrix();
+ int rows = m.length;
+ for (int row = 0; row < rows; row++)
+ {
+ assertEquals(m[row].length, rows);
+ for (int col = 0; col < rows; col++)
+ {
+ assertEquals(m[row][col], m[col][row], String.format("%s [%s, %s]",
+ sm.getName(), ResidueProperties.aa[row],
+ ResidueProperties.aa[col]));
+ }
+ }
+ }
+
+ /**
+ * A test that just asserts the expected values in the Blosum62 score matrix
+ */
+ @Test(groups = "Functional")
+ public void testBlosum62_values()
+ {
+ ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
+
+ assertTrue(sm.isProtein());
+ assertFalse(sm.isDNA());
+ assertNull(sm.getDescription());
+
+ /*
+ * verify expected scores against ARNDCQEGHILKMFPSTWYVBZX
+ * scraped from https://www.ncbi.nlm.nih.gov/Class/FieldGuide/BLOSUM62.txt
+ */
+ verifyValues(sm, 'A', new float[] { 4, -1, -2, -2, 0, -1, -1, 0, -2,
+ -1,
+ -1, -1, -1, -2, -1, 1, 0, -3, -2, 0, -2, -1, 0 });
+ verifyValues(sm, 'R', new float[] { -1, 5, 0, -2, -3, 1, 0, -2, 0, -3,
+ -2, 2, -1, -3, -2, -1, -1, -3, -2, -3, -1, 0, -1 });
+ verifyValues(sm, 'N', new float[] { -2, 0, 6, 1, -3, 0, 0, 0, 1, -3,
+ -3,
+ 0, -2, -3, -2, 1, 0, -4, -2, -3, 3, 0, -1 });
+ verifyValues(sm, 'D', new float[] { -2, -2, 1, 6, -3, 0, 2, -1, -1, -3,
+ -4, -1, -3, -3, -1, 0, -1, -4, -3, -3, 4, 1, -1 });
+ verifyValues(sm, 'C', new float[] { 0, -3, -3, -3, 9, -3, -4, -3, -3,
+ -1,
+ -1, -3, -1, -2, -3, -1, -1, -2, -2, -1, -3, -3, -2 });
+ verifyValues(sm, 'Q', new float[] { -1, 1, 0, 0, -3, 5, 2, -2, 0, -3,
+ -2,
+ 1, 0, -3, -1, 0, -1, -2, -1, -2, 0, 3, -1 });
+ verifyValues(sm, 'E', new float[] { -1, 0, 0, 2, -4, 2, 5, -2, 0, -3,
+ -3,
+ 1, -2, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1 });
+ verifyValues(sm, 'G', new float[] { 0, -2, 0, -1, -3, -2, -2, 6, -2,
+ -4,
+ -4, -2, -3, -3, -2, 0, -2, -2, -3, -3, -1, -2, -1 });
+ verifyValues(sm, 'H', new float[] { -2, 0, 1, -1, -3, 0, 0, -2, 8, -3,
+ -3, -1, -2, -1, -2, -1, -2, -2, 2, -3, 0, 0, -1 });
+ verifyValues(sm, 'I', new float[] { -1, -3, -3, -3, -1, -3, -3, -4, -3,
+ 4, 2, -3, 1, 0, -3, -2, -1, -3, -1, 3, -3, -3, -1 });
+ verifyValues(sm, 'L', new float[] { -1, -2, -3, -4, -1, -2, -3, -4, -3,
+ 2, 4, -2, 2, 0, -3, -2, -1, -2, -1, 1, -4, -3, -1 });
+ verifyValues(sm, 'K', new float[] { -1, 2, 0, -1, -3, 1, 1, -2, -1, -3,
+ -2, 5, -1, -3, -1, 0, -1, -3, -2, -2, 0, 1, -1 });
+ verifyValues(sm, 'M', new float[] { -1, -1, -2, -3, -1, 0, -2, -3, -2,
+ 1,
+ 2, -1, 5, 0, -2, -1, -1, -1, -1, 1, -3, -1, -1 });
+ verifyValues(sm, 'F', new float[] { -2, -3, -3, -3, -2, -3, -3, -3, -1,
+ 0, 0, -3, 0, 6, -4, -2, -2, 1, 3, -1, -3, -3, -1 });
+ verifyValues(sm, 'P', new float[] { -1, -2, -2, -1, -3, -1, -1, -2, -2,
+ -3, -3, -1, -2, -4, 7, -1, -1, -4, -3, -2, -2, -1, -2 });
+ verifyValues(sm, 'S', new float[] { 1, -1, 1, 0, -1, 0, 0, 0, -1, -2,
+ -2,
+ 0, -1, -2, -1, 4, 1, -3, -2, -2, 0, 0, 0 });
+ verifyValues(sm, 'T', new float[] { 0, -1, 0, -1, -1, -1, -1, -2, -2,
+ -1,
+ -1, -1, -1, -2, -1, 1, 5, -2, -2, 0, -1, -1, 0 });
+ verifyValues(sm, 'W', new float[] { -3, -3, -4, -4, -2, -2, -3, -2, -2,
+ -3, -2, -3, -1, 1, -4, -3, -2, 11, 2, -3, -4, -3, -2 });
+ verifyValues(sm, 'Y', new float[] { -2, -2, -2, -3, -2, -1, -2, -3, 2,
+ -1, -1, -2, -1, 3, -3, -2, -2, 2, 7, -1, -3, -2, -1 });
+ verifyValues(sm, 'V', new float[] { 0, -3, -3, -3, -1, -2, -2, -3, -3,
+ 3,
+ 1, -2, 1, -1, -2, -2, 0, -3, -1, 4, -3, -2, -1 });
+ verifyValues(sm, 'B', new float[] { -2, -1, 3, 4, -3, 0, 1, -1, 0, -3,
+ -4, 0, -3, -3, -2, 0, -1, -4, -3, -3, 4, 1, -1 });
+ verifyValues(sm, 'Z', new float[] { -1, 0, 0, 1, -3, 3, 4, -2, 0, -3,
+ -3,
+ 1, -1, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1 });
+ verifyValues(sm, 'X', new float[] { 0, -1, -1, -1, -2, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -2, 0, 0, -2, -1, -1, -1, -1, -1 });
+ }
+
+ /**
+ * Helper method to check pairwise scores for one residue
+ *
+ * @param sm
+ * @param res
+ * @param expected
+ * score values against 'res', in ResidueProperties.aaIndex order
+ */
+ private void verifyValues(ScoreMatrix sm, char res, float[] expected)
+ {
+ for (int j = 0; j < expected.length; j++)
+ {
+ char c2 = ResidueProperties.aa[j].charAt(0);
+ assertEquals(sm.getPairwiseScore(res, c2), expected[j],
+ String.format("%s->%s", res, c2));
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testConstructor_gapDash()
+ {
+ float[][] scores = new float[2][];
+ scores[0] = new float[] { 1f, 2f };
+ scores[1] = new float[] { 4f, 5f };
+ ScoreMatrix sm = new ScoreMatrix("Test", new char[] { 'A', '-' },
+ scores);
+ assertEquals(sm.getSize(), 2);
+ assertArrayEquals(scores, sm.getMatrix());
+ assertEquals(sm.getPairwiseScore('A', 'a'), 1f);
+ assertEquals(sm.getPairwiseScore('A', 'A'), 1f);
+ assertEquals(sm.getPairwiseScore('a', '-'), 2f);
+ assertEquals(sm.getPairwiseScore('-', 'A'), 4f);
+ assertEquals(sm.getMatrixIndex('a'), 0);
+ assertEquals(sm.getMatrixIndex('A'), 0);
+ assertEquals(sm.getMatrixIndex('-'), 1);
+ assertEquals(sm.getMatrixIndex(' '), -1);
+ assertEquals(sm.getMatrixIndex('.'), -1);
+ }
+
+ @Test(groups = "Functional")
+ public void testGetPairwiseScore()
+ {
+ float[][] scores = new float[2][];
+ scores[0] = new float[] { 1f, 2f };
+ scores[1] = new float[] { -4f, 5f };
+ ScoreMatrix sm = new ScoreMatrix("Test", new char[] { 'A', 'B' },
+ scores);
+ assertEquals(sm.getPairwiseScore('A', 'A'), 1f);
+ assertEquals(sm.getPairwiseScore('A', 'a'), 1f);
+ assertEquals(sm.getPairwiseScore('A', 'B'), 2f);
+ assertEquals(sm.getPairwiseScore('b', 'a'), -4f);
+ assertEquals(sm.getPairwiseScore('B', 'b'), 5f);
+
+ /*
+ * unknown symbols currently score minimum score
+ * or 1 for identity with self
+ */
+ assertEquals(sm.getPairwiseScore('A', '-'), -4f);
+ assertEquals(sm.getPairwiseScore('-', 'A'), -4f);
+ assertEquals(sm.getPairwiseScore('-', '-'), 1f);
+ assertEquals(sm.getPairwiseScore('Q', 'W'), -4f);
+ assertEquals(sm.getPairwiseScore('Q', 'Q'), 1f);
+
+ /*
+ * symbols not in basic ASCII set score zero
+ */
+ char c = (char) 200;
+ assertEquals(sm.getPairwiseScore('Q', c), 0f);
+ assertEquals(sm.getPairwiseScore(c, 'Q'), 0f);
+ }
+
+ @Test(groups = "Functional")
+ public void testGetMinimumScore()
+ {
+ ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
+ assertEquals(sm.getMinimumScore(), -4f);
+ }
+
+ @Test(groups = "Functional")
+ public void testGetMaximumScore()
+ {
+ ScoreMatrix sm = ScoreModels.getInstance().getBlosum62();
+ assertEquals(sm.getMaximumScore(), 11f);
+ }
+
+ @Test(groups = "Functional")
+ public void testOutputMatrix_html()
+ {
+ float[][] scores = new float[2][];
+ scores[0] = new float[] { 1f, 2f };
+ scores[1] = new float[] { 4f, -5.3E-10f };
+ ScoreMatrix sm = new ScoreMatrix("Test", "AB".toCharArray(), scores);
+ String html = sm.outputMatrix(true);
+ String expected = "<table border=\"1\"><tr><th></th><th> A </th><th> B </th></tr>\n"
+ + "<tr><td>A</td><td>1.0</td><td>2.0</td></tr>\n"
+ + "<tr><td>B</td><td>4.0</td><td>-5.3E-10</td></tr>\n"
+ + "</table>";
+ assertEquals(html, expected);
+ }
+}
--- /dev/null
+package jalview.analysis.scoremodels;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import jalview.api.analysis.PairwiseScoreModelI;
+import jalview.api.analysis.ScoreModelI;
+
+import java.util.Iterator;
+
+import org.testng.annotations.Test;
+
+public class ScoreModelsTest
+{
+ /**
+ * Verify that the singleton constructor successfully loads Jalview's built-in
+ * score models
+ */
+ @Test(groups = "Functional")
+ public void testConstructor()
+ {
+ Iterator<ScoreModelI> models = ScoreModels.getInstance().getModels()
+ .iterator();
+ assertTrue(models.hasNext());
+
+ /*
+ * models are served in order of addition
+ */
+ ScoreModelI sm = models.next();
+ assertTrue(sm instanceof SimilarityScoreModel);
+ assertTrue(sm instanceof PairwiseScoreModelI);
+ assertFalse(sm instanceof DistanceScoreModel);
+ assertEquals(sm.getName(), "BLOSUM62");
+ assertEquals(((PairwiseScoreModelI) sm).getPairwiseScore('I', 'R'), -3f);
+
+ sm = models.next();
+ assertTrue(sm instanceof SimilarityScoreModel);
+ assertTrue(sm instanceof PairwiseScoreModelI);
+ assertFalse(sm instanceof DistanceScoreModel);
+ assertEquals(sm.getName(), "PAM250");
+ assertEquals(((PairwiseScoreModelI) sm).getPairwiseScore('R', 'C'), -4f);
+
+ sm = models.next();
+ assertTrue(sm instanceof SimilarityScoreModel);
+ assertTrue(sm instanceof PairwiseScoreModelI);
+ assertFalse(sm instanceof DistanceScoreModel);
+ assertEquals(sm.getName(), "PID");
+ assertEquals(((PairwiseScoreModelI) sm).getPairwiseScore('R', 'C'), 0f);
+ assertEquals(((PairwiseScoreModelI) sm).getPairwiseScore('R', 'r'), 1f);
+
+ sm = models.next();
+ assertTrue(sm instanceof SimilarityScoreModel);
+ assertTrue(sm instanceof PairwiseScoreModelI);
+ assertFalse(sm instanceof DistanceScoreModel);
+ assertEquals(sm.getName(), "DNA");
+ assertEquals(((PairwiseScoreModelI) sm).getPairwiseScore('c', 'x'), 1f);
+
+ sm = models.next();
+ assertFalse(sm instanceof SimilarityScoreModel);
+ assertFalse(sm instanceof PairwiseScoreModelI);
+ assertTrue(sm instanceof DistanceScoreModel);
+ assertEquals(sm.getName(), "Sequence Feature Similarity");
+ }
+
+ /**
+ * 'Test' that prints out score matrices in tab-delimited format. This test is
+ * intentionally not assigned to any group so would not be run as part of a
+ * suite. It makes no assertions and is just provided as a utility method for
+ * printing out matrices. Relocated here from ScoreMatrixPrinter.
+ */
+ @Test(groups = "none")
+ public void printAllMatrices_tabDelimited()
+ {
+ printAllMatrices(false);
+ }
+
+ /**
+ * 'Test' that prints out score matrices in html format. This test is
+ * intentionally not assigned to any group so would not be run as part of a
+ * suite. It makes no assertions and is just provided as a utility method for
+ * printing out matrices. Relocated here from ScoreMatrixPrinter.
+ */
+ @Test(groups = "none")
+ public void printAllMatrices_asHtml()
+ {
+ printAllMatrices(true);
+ }
+
+ /**
+ * Print all registered ScoreMatrix as plain or html tables
+ *
+ * @param asHtml
+ */
+ protected void printAllMatrices(boolean asHtml)
+ {
+ for (ScoreModelI sm : ScoreModels.getInstance().getModels())
+ {
+ if (sm instanceof ScoreMatrix)
+ {
+ System.out.println(((ScoreMatrix) sm).outputMatrix(asHtml));
+ }
+ }
+ }
+}
import jalview.io.AppletFormatAdapter;
import jalview.io.FileFormat;
+import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
ann.getDefaultRnaHelixSymbol(i));
}
}
+
+ public static Annotation newAnnotation(String ann)
+ {
+ float val = 0f;
+ try
+ {
+ val = Float.parseFloat(ann);
+ } catch (NumberFormatException q)
+ {
+ }
+ ;
+ return new Annotation(ann, ann, '\0', val);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testIsQuantitative()
+ {
+ AlignmentAnnotation ann = null;
+
+ ann = new AlignmentAnnotation("an", "some an", null);
+ Assert.assertFalse(ann.isQuantitative(),
+ "Empty annotation set should not be quantitative.");
+
+ ann = new AlignmentAnnotation("an", "some an", new Annotation[] {
+ newAnnotation("4"), newAnnotation("1"), newAnnotation("1"),
+ newAnnotation("0.1"), newAnnotation("0.3") });
+ Assert.assertTrue(ann.isQuantitative(),
+ "All numbers annotation set should be quantitative.");
+
+ ann = new AlignmentAnnotation("an", "some an", new Annotation[] {
+ newAnnotation("E"), newAnnotation("E"), newAnnotation("E"),
+ newAnnotation("E"), newAnnotation("E") });
+ Assert.assertFalse(ann.isQuantitative(),
+ "All 'E' annotation set should not be quantitative.");
+
+ ann = new AlignmentAnnotation("an", "some an", new Annotation[] {
+ newAnnotation("E"), newAnnotation("1"), newAnnotation("2"),
+ newAnnotation("3"), newAnnotation("E") });
+ Assert.assertTrue(ann.isQuantitative(),
+ "Mixed 'E' annotation set should be quantitative.");
+ }
}
assertFalse(iter.hasNext());
}
+ /**
+ * Test method that returns annotations that match on reference sequence,
+ * label, or calcId.
+ */
+ @Test(groups = { "Functional" })
+ public void testFindAnnotations_bySeqLabelandorCalcId()
+ {
+ // TODO: finish testFindAnnotations_bySeqLabelandorCalcId test
+ /* Note - this is an incomplete test - need to check null or
+ * non-null [ matches, not matches ] behaviour for each of the three
+ * parameters..*/
+
+ // search for a single, unique calcId with wildcards on other params
+ Iterable<AlignmentAnnotation> anns = al.findAnnotations(null,
+ "CalcIdForD.melanogaster.2", null);
+ Iterator<AlignmentAnnotation> iter = anns.iterator();
+ assertTrue(iter.hasNext());
+ AlignmentAnnotation ann = iter.next();
+ assertEquals("D.melanogaster.2", ann.sequenceRef.getName());
+ assertFalse(iter.hasNext());
+
+ // save reference to test sequence reference parameter
+ SequenceI rseq = ann.sequenceRef;
+
+ // search for annotation associated with a single sequence
+ anns = al.findAnnotations(rseq, null, null);
+ iter = anns.iterator();
+ assertTrue(iter.hasNext());
+ ann = iter.next();
+ assertEquals("D.melanogaster.2", ann.sequenceRef.getName());
+ assertFalse(iter.hasNext());
+
+ // search for annotation with a non-existant calcId
+ anns = al.findAnnotations(null, "CalcIdForD.melanogaster.?", null);
+ iter = anns.iterator();
+ assertFalse(iter.hasNext());
+
+ // search for annotation with a particular label - expect three
+ anns = al.findAnnotations(null, null, "Secondary Structure");
+ iter = anns.iterator();
+ assertTrue(iter.hasNext());
+ iter.next();
+ assertTrue(iter.hasNext());
+ iter.next();
+ assertTrue(iter.hasNext());
+ iter.next();
+ // third found.. so
+ assertFalse(iter.hasNext());
+
+ // null on all parameters == find all annotations
+ anns = al.findAnnotations(null, null, null);
+ iter = anns.iterator();
+ int n = al.getAlignmentAnnotation().length;
+ while (iter.hasNext())
+ {
+ n--;
+ iter.next();
+ }
+ assertTrue("Found " + n + " fewer annotations from search.", n == 0);
+ }
+
@Test(groups = { "Functional" })
public void testDeleteAllAnnotations_includingAutocalculated()
{
import static org.testng.Assert.assertEquals;
+import jalview.gui.AlignFrame;
+import jalview.gui.AlignViewport;
import jalview.gui.JvOptionPane;
+import jalview.io.DataSourceType;
+import jalview.io.FileLoader;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
assertEquals(av.getVisibleAlignment('$').getSequenceAt(0)
.getSequenceAsString(), "A$$CDE");
}
+
+ @Test(groups = { "Functional" })
+ public void testGetVisibleContigs()
+ {
+ AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+ ">s1\n0123456789\n", DataSourceType.PASTE);
+ AlignViewport av = af.getViewport();
+ AlignmentView view = av.getAlignmentView(true);
+
+ /*
+ * verify getVisibleContigs returns inclusive [start, end] ranges
+ *
+ * no columns hidden
+ */
+ int[] contigs = view.getVisibleContigs();
+ assertEquals(contigs, new int[] { 0, 9 });
+
+ /*
+ * hide 3 internal columns
+ */
+ av.hideColumns(5, 7);
+ // the old AlignmentView is now stale!
+ contigs = view.getVisibleContigs();
+ assertEquals(contigs, new int[] { 0, 9 });
+ // get a fresh AlignmentView
+ view = av.getAlignmentView(true);
+ contigs = view.getVisibleContigs();
+ assertEquals(contigs, new int[] { 0, 4, 8, 9 });
+
+ // hide first 2 columns
+ av.hideColumns(0, 1);
+ view = av.getAlignmentView(true);
+ contigs = view.getVisibleContigs();
+ assertEquals(contigs, new int[] { 2, 4, 8, 9 });
+
+ // hide last column
+ av.hideColumns(9, 9);
+ view = av.getAlignmentView(true);
+ contigs = view.getVisibleContigs();
+ assertEquals(contigs, new int[] { 2, 4, 8, 8 });
+
+ // unhide columns 5-7
+ av.showColumn(5);
+ view = av.getAlignmentView(true);
+ contigs = view.getVisibleContigs();
+ assertEquals(contigs, new int[] { 2, 8 });
+
+ // hide columns 2-7
+ av.hideColumns(2, 7);
+ view = av.getAlignmentView(true);
+ contigs = view.getVisibleContigs();
+ assertEquals(contigs, new int[] { 8, 8 });
+
+ // hide column 8
+ av.hideColumns(8, 8);
+ view = av.getAlignmentView(true);
+ contigs = view.getVisibleContigs();
+ assertEquals(contigs, new int[] {});
+
+ // unhide all
+ av.showAllHiddenColumns();
+ view = av.getAlignmentView(true);
+ contigs = view.getVisibleContigs();
+ assertEquals(contigs, new int[] { 0, 9 });
+ }
}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertTrue;
+
+import java.util.NoSuchElementException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class AllColsIteratorTest
+{
+ HiddenColumns hiddenCols;
+
+ @BeforeClass
+ public void setup()
+ {
+ hiddenCols = new HiddenColumns();
+ hiddenCols.hideColumns(2,4);
+ }
+
+
+ /*
+ * Test iterator iterates through collection correctly
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNext()
+ {
+ AllColsIterator it = new AllColsIterator(0, 3, hiddenCols);
+ int count = 0;
+ while (it.hasNext())
+ {
+ it.next();
+ count++;
+ }
+ assertTrue(count == 4, "hasNext() is false after 4 iterations");
+ }
+
+ /*
+ * Test iterator throws NoSuchElementException at end of iteration
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNext() throws NoSuchElementException
+ {
+ AllColsIterator it = new AllColsIterator(0, 3, hiddenCols);
+ while (it.hasNext())
+ {
+ it.next();
+ }
+ it.next();
+ }
+
+ /*
+ * Test iterator throws UnsupportedOperationException on call to remove
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { UnsupportedOperationException.class })
+ public void testRemove() throws UnsupportedOperationException
+ {
+ AllColsIterator it = new AllColsIterator(0, 3, hiddenCols);
+ it.remove();
+ }
+
+ /*
+ * Test iterator behaves correctly when there is only one element in the collection
+ */
+ @Test(groups = { "Functional" })
+ public void testOneElement()
+ {
+ HiddenColumns hidden = new HiddenColumns();
+ AllColsIterator it = new AllColsIterator(0, 0, hidden);
+ int count = 0;
+ while (it.hasNext())
+ {
+ it.next();
+ count++;
+ }
+ assertTrue(count == 1, "hasNext() is false after 1 iteration");
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertTrue;
+
+import jalview.analysis.AlignmentGenerator;
+
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class AllRowsIteratorTest
+{
+ AlignmentI al;
+
+ Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<>();
+
+ @BeforeClass
+ public void setup()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ al = gen.generate(20, 15, 123, 5, 5);
+ if (!hiddenRepSequences.isEmpty())
+ {
+ al.getHiddenSequences().showAll(hiddenRepSequences);
+ }
+ hideSequences(2, 4);
+ }
+
+ /*
+ * Test iterator iterates through collection correctly
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNext()
+ {
+ AllRowsIterator it = new AllRowsIterator(0, 3, al);
+ int count = 0;
+ while (it.hasNext())
+ {
+ it.next();
+ count++;
+ }
+ assertTrue(count == 4, "hasNext() is false after 4 iterations");
+ }
+
+ /*
+ * Test iterator throws NoSuchElementException at end of iteration
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNext() throws NoSuchElementException
+ {
+ AllRowsIterator it = new AllRowsIterator(0, 3, al);
+ while (it.hasNext())
+ {
+ it.next();
+ }
+ it.next();
+ }
+
+ /*
+ * Test iterator throws UnsupportedOperationException on call to remove
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { UnsupportedOperationException.class })
+ public void testRemove() throws UnsupportedOperationException
+ {
+ AllRowsIterator it = new AllRowsIterator(0, 3, al);
+ it.remove();
+ }
+
+
+ /*
+ * Hide sequences between start and end
+ */
+ private void hideSequences(int start, int end)
+ {
+ SequenceI[] allseqs = al.getSequencesArray();
+ SequenceGroup theseSeqs = new SequenceGroup();
+
+ for (int i = start; i <= end; i++)
+ {
+ theseSeqs.addSequence(allseqs[i], false);
+ al.getHiddenSequences().hideSequence(allseqs[i]);
+ }
+
+ hiddenRepSequences.put(allseqs[start], theseSeqs);
+ }
+
+ /*
+ * Test iterator behaves correctly when there is only one element in the collection
+ */
+ @Test(groups = { "Functional" })
+ public void testOneElement()
+ {
+ AllRowsIterator it = new AllRowsIterator(0, 0, al);
+ int count = 0;
+ while (it.hasNext())
+ {
+ it.next();
+ count++;
+ }
+ assertTrue(count == 1, "hasNext() is false after 1 iteration");
+ }
+
+}
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
-import static org.testng.AssertJUnit.assertSame;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.AssertJUnit.fail;
+import jalview.analysis.AlignmentGenerator;
import jalview.gui.JvOptionPane;
import java.util.Arrays;
assertEquals("[2, 5, 3]", sel.toString());
}
+ @Test(groups = { "Functional" })
+ public void testSetElementsFrom()
+ {
+ ColumnSelection fromcs = new ColumnSelection();
+ ColumnSelection tocs = new ColumnSelection();
+ HiddenColumns hidden = new HiddenColumns();
+
+ fromcs.addElement(2);
+ fromcs.addElement(3);
+ fromcs.addElement(5);
+
+ tocs.setElementsFrom(fromcs, hidden);
+ assertTrue(tocs.equals(fromcs));
+
+ hidden.hideColumns(4, 6);
+ tocs.setElementsFrom(fromcs, hidden);
+
+ // expect cols 2 and 3 to be selected but not 5
+ ColumnSelection expectcs = new ColumnSelection();
+ expectcs.addElement(2);
+ expectcs.addElement(3);
+ assertTrue(tocs.equals(expectcs));
+ }
+
/**
* Test the remove method - in particular to verify that remove(int i) removes
* the element whose value is i, _NOT_ the i'th element.
}
/**
- * Test the method that finds the visible column position of an alignment
- * column, allowing for hidden columns.
- */
- @Test(groups = { "Functional" })
- public void testFindColumnPosition()
- {
- ColumnSelection cs = new ColumnSelection();
- assertEquals(5, cs.findColumnPosition(5));
-
- // hiding column 6 makes no difference
- cs.hideColumns(6, 6);
- assertEquals(5, cs.findColumnPosition(5));
-
- // hiding column 4 moves column 5 to column 4
- cs.hideColumns(4, 4);
- assertEquals(4, cs.findColumnPosition(5));
-
- // hiding column 4 moves column 4 to position 3
- assertEquals(3, cs.findColumnPosition(4));
-
- // hiding columns 1 and 2 moves column 5 to column 2
- cs.hideColumns(1, 2);
- assertEquals(2, cs.findColumnPosition(5));
-
- // check with > 1 hidden column regions
- // where some columns are in the hidden regions
- ColumnSelection cs2 = new ColumnSelection();
- cs2.hideColumns(5, 10);
- cs2.hideColumns(20, 27);
- cs2.hideColumns(40, 44);
-
- // hiding columns 5-10 and 20-27 moves column 8 to column 4
- assertEquals(4, cs2.findColumnPosition(8));
-
- // and moves column 24 to 13
- assertEquals(13, cs2.findColumnPosition(24));
-
- // and moves column 28 to 14
- assertEquals(14, cs2.findColumnPosition(28));
-
- // and moves column 40 to 25
- assertEquals(25, cs2.findColumnPosition(40));
-
- // check when hidden columns start at 0 that the visible column
- // is returned as 0
- ColumnSelection cs3 = new ColumnSelection();
- cs3.hideColumns(0, 4);
- assertEquals(0, cs3.findColumnPosition(2));
-
- }
-
- /**
- * Test the method that finds the visible column position a given distance
- * before another column
- */
- @Test(groups = { "Functional" })
- public void testFindColumnNToLeft()
- {
- ColumnSelection cs = new ColumnSelection();
-
- // test that without hidden columns, findColumnNToLeft returns
- // position n to left of provided position
- int pos = cs.subtractVisibleColumns(3, 10);
- assertEquals(7, pos);
-
- // 0 returns same position
- pos = cs.subtractVisibleColumns(0, 10);
- assertEquals(10, pos);
-
- // overflow to left returns negative number
- pos = cs.subtractVisibleColumns(3, 0);
- assertEquals(-3, pos);
-
- // test that with hidden columns to left of result column
- // behaviour is the same as above
- cs.hideColumns(1, 3);
-
- // position n to left of provided position
- pos = cs.subtractVisibleColumns(3, 10);
- assertEquals(7, pos);
-
- // 0 returns same position
- pos = cs.subtractVisibleColumns(0, 10);
- assertEquals(10, pos);
-
- // test with one set of hidden columns between start and required position
- cs.hideColumns(12, 15);
- pos = cs.subtractVisibleColumns(8, 17);
- assertEquals(5, pos);
-
- // test with two sets of hidden columns between start and required position
- cs.hideColumns(20, 21);
- pos = cs.subtractVisibleColumns(8, 23);
- assertEquals(9, pos);
-
- // repeat last 2 tests with no hidden columns to left of required position
- cs.revealAllHiddenColumns();
-
- // test with one set of hidden columns between start and required position
- cs.hideColumns(12, 15);
- pos = cs.subtractVisibleColumns(8, 17);
- assertEquals(5, pos);
-
- // test with two sets of hidden columns between start and required position
- cs.hideColumns(20, 21);
- pos = cs.subtractVisibleColumns(8, 23);
- assertEquals(9, pos);
-
- }
-
- /**
- * Test the code used to locate the reference sequence ruler origin
- */
- @Test(groups = { "Functional" })
- public void testLocateVisibleBoundsofSequence()
- {
- ColumnSelection cs = new ColumnSelection();
- SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
- assertEquals(2, seq.findIndex(seq.getStart()));
-
- // no hidden columns
- assertEquals(
- Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
- seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
- seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
- seq.findIndex(seq.getEnd()) - 1 }),
- Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
-
- // hidden column on gap after end of sequence - should not affect bounds
- cs.hideColumns(13);
- assertEquals(
- Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
- seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
- seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
- seq.findIndex(seq.getEnd()) - 1 }),
- Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
-
- cs.revealAllHiddenColumns();
- // hidden column on gap before beginning of sequence - should vis bounds by
- // one
- cs.hideColumns(0);
- assertEquals(
- Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 2,
- seq.findIndex(seq.getEnd()) - 2, seq.getStart(),
- seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
- seq.findIndex(seq.getEnd()) - 1 }),
- Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
-
- cs.revealAllHiddenColumns();
- // hide columns around most of sequence - leave one residue remaining
- cs.hideColumns(1, 3);
- cs.hideColumns(6, 11);
- assertEquals("-D",
- cs.getVisibleSequenceStrings(0, 5, new SequenceI[] { seq })[0]);
- assertEquals(
- Arrays.toString(new int[] { 1, 1, 3, 3,
- seq.findIndex(seq.getStart()) - 1,
- seq.findIndex(seq.getEnd()) - 1 }),
- Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
- cs.revealAllHiddenColumns();
-
- // hide whole sequence - should just get location of hidden region
- // containing sequence
- cs.hideColumns(1, 11);
- assertEquals(
- Arrays.toString(new int[] { 0, 1, 0, 0,
- seq.findIndex(seq.getStart()) - 1,
- seq.findIndex(seq.getEnd()) - 1 }),
- Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
-
- }
-
- @Test(groups = { "Functional" })
- public void testLocateVisibleBoundsPathologicals()
- {
- // test some pathological cases we missed
- AlignmentI al = new Alignment(new SequenceI[] { new Sequence(
- "refseqGaptest", "KTDVTI----------NFI-----G----L") });
- ColumnSelection cs = new ColumnSelection();
- cs.hideInsertionsFor(al.getSequenceAt(0));
- assertEquals(
- "G",
- ""
- + al.getSequenceAt(0).getCharAt(
- cs.adjustForHiddenColumns(9)));
-
- }
-
- @Test(groups = { "Functional" })
- public void testHideColumns()
- {
- ColumnSelection cs = new ColumnSelection();
- cs.hideColumns(5);
- List<int[]> hidden = cs.getHiddenColumns();
- assertEquals(1, hidden.size());
- assertEquals("[5, 5]", Arrays.toString(hidden.get(0)));
-
- cs.hideColumns(3);
- assertEquals(2, hidden.size());
- // two hidden ranges, in order:
- assertSame(hidden, cs.getHiddenColumns());
- assertEquals("[3, 3]", Arrays.toString(hidden.get(0)));
- assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
-
- // hiding column 4 expands [3, 3] to [3, 4]
- // and merges to [5, 5] to make [3, 5]
- cs.hideColumns(4);
- hidden = cs.getHiddenColumns();
- assertEquals(1, hidden.size());
- assertEquals("[3, 5]", Arrays.toString(hidden.get(0)));
-
- // clear hidden columns (note they are added to selected)
- cs.revealAllHiddenColumns();
- // it is now actually null but getter returns an empty list
- assertTrue(cs.getHiddenColumns().isEmpty());
-
- cs.hideColumns(3, 6);
- hidden = cs.getHiddenColumns();
- int[] firstHiddenRange = hidden.get(0);
- assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
-
- // adding a subrange of already hidden should do nothing
- cs.hideColumns(4, 5);
- assertEquals(1, hidden.size());
- assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
- cs.hideColumns(3, 5);
- assertEquals(1, hidden.size());
- assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
- cs.hideColumns(4, 6);
- assertEquals(1, hidden.size());
- assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
- cs.hideColumns(3, 6);
- assertEquals(1, hidden.size());
- assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
-
- cs.revealAllHiddenColumns();
- cs.hideColumns(2, 4);
- hidden = cs.getHiddenColumns();
- assertEquals(1, hidden.size());
- assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
-
- // extend contiguous with 2 positions overlap
- cs.hideColumns(3, 5);
- assertEquals(1, hidden.size());
- assertEquals("[2, 5]", Arrays.toString(hidden.get(0)));
-
- // extend contiguous with 1 position overlap
- cs.hideColumns(5, 6);
- assertEquals(1, hidden.size());
- assertEquals("[2, 6]", Arrays.toString(hidden.get(0)));
-
- // extend contiguous with overlap both ends:
- cs.hideColumns(1, 7);
- assertEquals(1, hidden.size());
- assertEquals("[1, 7]", Arrays.toString(hidden.get(0)));
- }
-
- /**
* Test the method that hides a specified column including any adjacent
* selected columns. This is a convenience method for the case where multiple
* column regions are selected and then hidden using menu option View | Hide |
@Test(groups = { "Functional" })
public void testHideColumns_withSelection()
{
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI al = gen.generate(50, 20, 123, 5, 5);
+
ColumnSelection cs = new ColumnSelection();
// select columns 4-6
cs.addElement(4);
cs.addElement(5);
cs.addElement(6);
// hide column 5 (and adjacent):
- cs.hideColumns(5);
+ cs.hideSelectedColumns(5, al.getHiddenColumns());
// 4,5,6 now hidden:
- List<int[]> hidden = cs.getHiddenColumns();
+ List<int[]> hidden = al.getHiddenColumns().getHiddenRegions();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
// none now selected:
assertTrue(cs.getSelected().isEmpty());
// repeat, hiding column 4 (5 and 6)
+ al = gen.generate(50, 20, 123, 5, 5);
cs = new ColumnSelection();
cs.addElement(4);
cs.addElement(5);
cs.addElement(6);
- cs.hideColumns(4);
- hidden = cs.getHiddenColumns();
+ cs.hideSelectedColumns(4, al.getHiddenColumns());
+ hidden = al.getHiddenColumns().getHiddenRegions();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
assertTrue(cs.getSelected().isEmpty());
// repeat, hiding column (4, 5 and) 6
+ al = gen.generate(50, 20, 123, 5, 5);
cs = new ColumnSelection();
cs.addElement(4);
cs.addElement(5);
cs.addElement(6);
- cs.hideColumns(6);
- hidden = cs.getHiddenColumns();
+ cs.hideSelectedColumns(6, al.getHiddenColumns());
+ hidden = al.getHiddenColumns().getHiddenRegions();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
assertTrue(cs.getSelected().isEmpty());
// repeat, with _only_ adjacent columns selected
+ al = gen.generate(50, 20, 123, 5, 5);
cs = new ColumnSelection();
cs.addElement(4);
cs.addElement(6);
- cs.hideColumns(5);
- hidden = cs.getHiddenColumns();
+ cs.hideSelectedColumns(5, al.getHiddenColumns());
+ hidden = al.getHiddenColumns().getHiddenRegions();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
assertTrue(cs.getSelected().isEmpty());
@Test(groups = { "Functional" })
public void testHideSelectedColumns()
{
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI al = gen.generate(50, 20, 123, 5, 5);
+
ColumnSelection cs = new ColumnSelection();
int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
for (int col : sel)
{
cs.addElement(col);
}
- cs.hideColumns(15, 18);
- cs.hideSelectedColumns();
+ HiddenColumns cols = al.getHiddenColumns();
+ cols.hideColumns(15, 18);
+
+ cs.hideSelectedColumns(al);
assertTrue(cs.getSelected().isEmpty());
- List<int[]> hidden = cs.getHiddenColumns();
+ List<int[]> hidden = cols.getHiddenRegions();
assertEquals(4, hidden.size());
assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
assertEquals("[7, 9]", Arrays.toString(hidden.get(1)));
assertEquals("[0, 4]", Arrays.toString(range.get(0)));
}
- /**
- * Test the method that reveals a range of hidden columns given the start
- * column of the range
- */
- @Test(groups = { "Functional" })
- public void testRevealHiddenColumns()
- {
- ColumnSelection cs = new ColumnSelection();
- cs.hideColumns(5, 8);
- cs.addElement(10);
- cs.revealHiddenColumns(5);
- // hidden columns list now null but getter returns empty list:
- assertTrue(cs.getHiddenColumns().isEmpty());
- // revealed columns are marked as selected (added to selection):
- assertEquals("[10, 5, 6, 7, 8]", cs.getSelected().toString());
-
- // calling with a column other than the range start does nothing:
- cs = new ColumnSelection();
- cs.hideColumns(5, 8);
- List<int[]> hidden = cs.getHiddenColumns();
- cs.revealHiddenColumns(6);
- assertSame(hidden, cs.getHiddenColumns());
- assertTrue(cs.getSelected().isEmpty());
- }
-
- @Test(groups = { "Functional" })
- public void testRevealAllHiddenColumns()
- {
- ColumnSelection cs = new ColumnSelection();
- cs.hideColumns(5, 8);
- cs.hideColumns(2, 3);
- cs.addElement(11);
- cs.addElement(1);
- cs.revealAllHiddenColumns();
-
- /*
- * revealing hidden columns adds them (in order) to the (unordered)
- * selection list
- */
- assertTrue(cs.getHiddenColumns().isEmpty());
- assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]", cs.getSelected().toString());
- }
-
- @Test(groups = { "Functional" })
- public void testIsVisible()
- {
- ColumnSelection cs = new ColumnSelection();
- cs.hideColumns(2, 4);
- cs.hideColumns(6, 7);
- assertTrue(cs.isVisible(0));
- assertTrue(cs.isVisible(-99));
- assertTrue(cs.isVisible(1));
- assertFalse(cs.isVisible(2));
- assertFalse(cs.isVisible(3));
- assertFalse(cs.isVisible(4));
- assertTrue(cs.isVisible(5));
- assertFalse(cs.isVisible(6));
- assertFalse(cs.isVisible(7));
- }
-
- @Test(groups = { "Functional" })
- public void testGetVisibleContigs()
- {
- ColumnSelection cs = new ColumnSelection();
- cs.hideColumns(3, 6);
- cs.hideColumns(8, 9);
- cs.hideColumns(12, 12);
-
- // start position is inclusive, end position exclusive:
- int[] visible = cs.getVisibleContigs(1, 13);
- assertEquals("[1, 2, 7, 7, 10, 11]", Arrays.toString(visible));
-
- visible = cs.getVisibleContigs(4, 14);
- assertEquals("[7, 7, 10, 11, 13, 13]", Arrays.toString(visible));
-
- visible = cs.getVisibleContigs(3, 10);
- assertEquals("[7, 7]", Arrays.toString(visible));
-
- visible = cs.getVisibleContigs(4, 6);
- assertEquals("[]", Arrays.toString(visible));
- }
-
@Test(groups = { "Functional" })
public void testInvertColumnSelection()
{
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI al = gen.generate(50, 20, 123, 5, 5);
+
ColumnSelection cs = new ColumnSelection();
cs.addElement(4);
cs.addElement(6);
cs.addElement(8);
- cs.hideColumns(3, 3);
- cs.hideColumns(6, 6);
+
+ HiddenColumns cols = al.getHiddenColumns();
+ cols.hideColumns(3, 3);
+ cols.hideColumns(6, 6);
// invert selection from start (inclusive) to end (exclusive)
- // hidden columns are _not_ changed
- cs.invertColumnSelection(2, 9);
+ cs.invertColumnSelection(2, 9, al);
assertEquals("[2, 5, 7]", cs.getSelected().toString());
- cs.invertColumnSelection(1, 9);
+ cs.invertColumnSelection(1, 9, al);
assertEquals("[1, 4, 8]", cs.getSelected().toString());
}
cs.addElement(0);
cs.addElement(513);
cs.addElement(1);
- cs.hideColumns(3);
- cs.hideColumns(7);
- cs.hideColumns(5, 9);
// same selections added in a different order
ColumnSelection cs2 = new ColumnSelection();
cs2.addElement(513);
cs2.addElement(0);
- // with no hidden columns
- assertFalse(cs.equals(cs2));
- assertFalse(cs2.equals(cs));
-
- // with hidden columns added in a different order
- cs2.hideColumns(6, 9);
- cs2.hideColumns(5, 8);
- cs2.hideColumns(3);
-
assertTrue(cs.equals(cs2));
assertTrue(cs.equals(cs));
assertTrue(cs2.equals(cs));
cs2.removeElement(12);
assertTrue(cs.equals(cs2));
-
- cs2.hideColumns(88);
- assertFalse(cs.equals(cs2));
- /*
- * unhiding a column adds it to selection!
- */
- cs2.revealHiddenColumns(88);
- assertFalse(cs.equals(cs2));
- cs.addElement(88);
- assertTrue(cs.equals(cs2));
}
+ /*
+ cs2.hideSelectedColumns(88);
+ assertFalse(cs.equals(cs2));
+ /*
+ * unhiding a column adds it to selection!
+ */
+ /* cs2.revealHiddenColumns(88);
+ assertFalse(cs.equals(cs2));
+ cs.addElement(88);
+ assertTrue(cs.equals(cs2));
+ */
+
/**
* Test the method that returns selected columns, in the order in which they
* were added
ColumnSelection cs = new ColumnSelection();
cs.addElement(3);
cs.addElement(1);
- cs.hideColumns(10, 11);
- cs.hideColumns(5, 7);
- assertEquals("[5, 7]", Arrays.toString(cs.getHiddenColumns().get(0)));
ColumnSelection cs2 = new ColumnSelection(cs);
assertTrue(cs2.hasSelectedColumns());
- assertTrue(cs2.hasHiddenColumns());
+
// order of column selection is preserved
assertEquals("[3, 1]", cs2.getSelected().toString());
- assertEquals(2, cs2.getHiddenColumns().size());
- // hidden columns are held in column order
- assertEquals("[5, 7]", Arrays.toString(cs2.getHiddenColumns().get(0)));
- assertEquals("[10, 11]", Arrays.toString(cs2.getHiddenColumns().get(1)));
}
- /**
- * Test for the case when a hidden range encloses more one already hidden
- * range
- */
- @Test(groups = { "Functional" })
- public void testHideColumns_subsumingHidden()
- {
- /*
- * JAL-2370 bug scenario:
- * two hidden ranges subsumed by a third
- */
- ColumnSelection cs = new ColumnSelection();
- cs.hideColumns(49, 59);
- cs.hideColumns(69, 79);
- List<int[]> hidden = cs.getHiddenColumns();
- assertEquals(2, hidden.size());
- assertEquals("[49, 59]", Arrays.toString(hidden.get(0)));
- assertEquals("[69, 79]", Arrays.toString(hidden.get(1)));
-
- cs.hideColumns(48, 80);
- hidden = cs.getHiddenColumns();
- assertEquals(1, hidden.size());
- assertEquals("[48, 80]", Arrays.toString(hidden.get(0)));
-
- /*
- * another...joining hidden ranges
- */
- cs = new ColumnSelection();
- cs.hideColumns(10, 20);
- cs.hideColumns(30, 40);
- cs.hideColumns(50, 60);
- // hiding 21-49 should merge to one range
- cs.hideColumns(21, 49);
- hidden = cs.getHiddenColumns();
- assertEquals(1, hidden.size());
- assertEquals("[10, 60]", Arrays.toString(hidden.get(0)));
-
- /*
- * another...lef overlap, subsumption, right overlap,
- * no overlap of existing hidden ranges
- */
- cs = new ColumnSelection();
- cs.hideColumns(10, 20);
- cs.hideColumns(10, 20);
- cs.hideColumns(30, 35);
- cs.hideColumns(40, 50);
- cs.hideColumns(60, 70);
-
- cs.hideColumns(15, 45);
- hidden = cs.getHiddenColumns();
- assertEquals(2, hidden.size());
- assertEquals("[10, 50]", Arrays.toString(hidden.get(0)));
- assertEquals("[60, 70]", Arrays.toString(hidden.get(1)));
- }
@Test(groups = { "Functional" })
public void testStretchGroup_expand()
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertSame;
+import static org.testng.AssertJUnit.assertTrue;
+
+import jalview.analysis.AlignmentGenerator;
+import jalview.gui.JvOptionPane;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class HiddenColumnsTest
+{
+
+ @BeforeClass(alwaysRun = true)
+ public void setUpJvOptionPane()
+ {
+ JvOptionPane.setInteractiveMode(false);
+ JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+ }
+
+ /**
+ * Test the method which counts the number of hidden columns
+ */
+ @Test(groups = { "Functional" })
+ public void testGetSize()
+ {
+ HiddenColumns hidden = new HiddenColumns();
+ assertEquals(0, hidden.getSize());
+
+ hidden.hideColumns(3, 5);
+ assertEquals(3, hidden.getSize());
+
+ hidden.hideColumns(8, 8);
+ assertEquals(4, hidden.getSize());
+
+ hidden.hideColumns(9, 14);
+ assertEquals(10, hidden.getSize());
+
+ ColumnSelection cs = new ColumnSelection();
+ hidden.revealAllHiddenColumns(cs);
+ assertEquals(0, hidden.getSize());
+ }
+
+ /**
+ * Test the method that finds the visible column position of an alignment
+ * column, allowing for hidden columns.
+ */
+ @Test(groups = { "Functional" })
+ public void testFindColumnPosition()
+ {
+ HiddenColumns cs = new HiddenColumns();
+ assertEquals(5, cs.findColumnPosition(5));
+
+ // hiding column 6 makes no difference
+ cs.hideColumns(6, 6);
+ assertEquals(5, cs.findColumnPosition(5));
+
+ // hiding column 4 moves column 5 to column 4
+ cs.hideColumns(4, 4);
+ assertEquals(4, cs.findColumnPosition(5));
+
+ // hiding column 4 moves column 4 to position 3
+ assertEquals(3, cs.findColumnPosition(4));
+
+ // hiding columns 1 and 2 moves column 5 to column 2
+ cs.hideColumns(1, 2);
+ assertEquals(2, cs.findColumnPosition(5));
+
+ // check with > 1 hidden column regions
+ // where some columns are in the hidden regions
+ HiddenColumns cs2 = new HiddenColumns();
+ cs2.hideColumns(5, 10);
+ cs2.hideColumns(20, 27);
+ cs2.hideColumns(40, 44);
+
+ // hiding columns 5-10 and 20-27 moves column 8 to column 4
+ assertEquals(4, cs2.findColumnPosition(8));
+
+ // and moves column 24 to 13
+ assertEquals(13, cs2.findColumnPosition(24));
+
+ // and moves column 28 to 14
+ assertEquals(14, cs2.findColumnPosition(28));
+
+ // and moves column 40 to 25
+ assertEquals(25, cs2.findColumnPosition(40));
+
+ // check when hidden columns start at 0 that the visible column
+ // is returned as 0
+ HiddenColumns cs3 = new HiddenColumns();
+ cs3.hideColumns(0, 4);
+ assertEquals(0, cs3.findColumnPosition(2));
+
+ }
+
+ /**
+ * Test the method that finds the visible column position a given distance
+ * before another column
+ */
+ @Test(groups = { "Functional" })
+ public void testFindColumnNToLeft()
+ {
+ HiddenColumns cs = new HiddenColumns();
+
+ // test that without hidden columns, findColumnNToLeft returns
+ // position n to left of provided position
+ int pos = cs.subtractVisibleColumns(3, 10);
+ assertEquals(7, pos);
+
+ // 0 returns same position
+ pos = cs.subtractVisibleColumns(0, 10);
+ assertEquals(10, pos);
+
+ // overflow to left returns negative number
+ pos = cs.subtractVisibleColumns(3, 0);
+ assertEquals(-3, pos);
+
+ // test that with hidden columns to left of result column
+ // behaviour is the same as above
+ cs.hideColumns(1, 3);
+
+ // position n to left of provided position
+ pos = cs.subtractVisibleColumns(3, 10);
+ assertEquals(7, pos);
+
+ // 0 returns same position
+ pos = cs.subtractVisibleColumns(0, 10);
+ assertEquals(10, pos);
+
+ // test with one set of hidden columns between start and required position
+ cs.hideColumns(12, 15);
+ pos = cs.subtractVisibleColumns(8, 17);
+ assertEquals(5, pos);
+
+ // test with two sets of hidden columns between start and required position
+ cs.hideColumns(20, 21);
+ pos = cs.subtractVisibleColumns(8, 23);
+ assertEquals(9, pos);
+
+ // repeat last 2 tests with no hidden columns to left of required position
+ ColumnSelection colsel = new ColumnSelection();
+ cs.revealAllHiddenColumns(colsel);
+
+ // test with one set of hidden columns between start and required position
+ cs.hideColumns(12, 15);
+ pos = cs.subtractVisibleColumns(8, 17);
+ assertEquals(5, pos);
+
+ // test with two sets of hidden columns between start and required position
+ cs.hideColumns(20, 21);
+ pos = cs.subtractVisibleColumns(8, 23);
+ assertEquals(9, pos);
+
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetVisibleContigs()
+ {
+ HiddenColumns cs = new HiddenColumns();
+ cs.hideColumns(3, 6);
+ cs.hideColumns(8, 9);
+ cs.hideColumns(12, 12);
+
+ // start position is inclusive, end position exclusive:
+ int[] visible = cs.getVisibleContigs(1, 13);
+ assertEquals("[1, 2, 7, 7, 10, 11]", Arrays.toString(visible));
+
+ visible = cs.getVisibleContigs(4, 14);
+ assertEquals("[7, 7, 10, 11, 13, 13]", Arrays.toString(visible));
+
+ visible = cs.getVisibleContigs(3, 10);
+ assertEquals("[7, 7]", Arrays.toString(visible));
+
+ visible = cs.getVisibleContigs(4, 6);
+ assertEquals("[]", Arrays.toString(visible));
+ }
+
+ @Test(groups = { "Functional" })
+ public void testEquals()
+ {
+ HiddenColumns cs = new HiddenColumns();
+ cs.hideColumns(5, 9);
+
+ // a different set of hidden columns
+ HiddenColumns cs2 = new HiddenColumns();
+
+ // with no hidden columns
+ assertFalse(cs.equals(cs2));
+ assertFalse(cs2.equals(cs));
+
+ // with hidden columns added in a different order
+ cs2.hideColumns(6, 9);
+ cs2.hideColumns(5, 8);
+
+ assertTrue(cs.equals(cs2));
+ assertTrue(cs.equals(cs));
+ assertTrue(cs2.equals(cs));
+ assertTrue(cs2.equals(cs2));
+ }
+
+ @Test(groups = "Functional")
+ public void testCopyConstructor()
+ {
+ HiddenColumns cs = new HiddenColumns();
+ cs.hideColumns(10, 11);
+ cs.hideColumns(5, 7);
+ assertEquals("[5, 7]", Arrays.toString(cs.getHiddenRegions().get(0)));
+
+ HiddenColumns cs2 = new HiddenColumns(cs);
+ assertTrue(cs2.hasHiddenColumns());
+ assertEquals(2, cs2.getHiddenRegions().size());
+ // hidden columns are held in column order
+ assertEquals("[5, 7]", Arrays.toString(cs2.getHiddenRegions().get(0)));
+ assertEquals("[10, 11]", Arrays.toString(cs2.getHiddenRegions().get(1)));
+ }
+
+ /**
+ * Test the code used to locate the reference sequence ruler origin
+ */
+ @Test(groups = { "Functional" })
+ public void testLocateVisibleBoundsofSequence()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI al = gen.generate(50, 20, 123, 5, 5);
+
+ HiddenColumns cs = al.getHiddenColumns();
+ ColumnSelection colsel = new ColumnSelection();
+
+ SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
+ assertEquals(2, seq.findIndex(seq.getStart()));
+
+ // no hidden columns
+ assertEquals(
+ Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
+ seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
+ seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
+ seq.findIndex(seq.getEnd()) - 1 }),
+ Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
+
+ // hidden column on gap after end of sequence - should not affect bounds
+ colsel.hideSelectedColumns(13, al.getHiddenColumns());
+ assertEquals(
+ Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
+ seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
+ seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
+ seq.findIndex(seq.getEnd()) - 1 }),
+ Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
+
+ cs.revealAllHiddenColumns(colsel);
+ // hidden column on gap before beginning of sequence - should vis bounds by
+ // one
+ colsel.hideSelectedColumns(0, al.getHiddenColumns());
+ assertEquals(
+ Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 2,
+ seq.findIndex(seq.getEnd()) - 2, seq.getStart(),
+ seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
+ seq.findIndex(seq.getEnd()) - 1 }),
+ Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
+
+ cs.revealAllHiddenColumns(colsel);
+ // hide columns around most of sequence - leave one residue remaining
+ cs.hideColumns(1, 3);
+ cs.hideColumns(6, 11);
+ assertEquals("-D",
+ cs.getVisibleSequenceStrings(0, 5, new SequenceI[] { seq })[0]);
+ assertEquals(
+ Arrays.toString(new int[] { 1, 1, 3, 3,
+ seq.findIndex(seq.getStart()) - 1,
+ seq.findIndex(seq.getEnd()) - 1 }),
+ Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
+ cs.revealAllHiddenColumns(colsel);
+
+ // hide whole sequence - should just get location of hidden region
+ // containing sequence
+ cs.hideColumns(1, 11);
+ assertEquals(
+ Arrays.toString(new int[] { 0, 1, 0, 0,
+ seq.findIndex(seq.getStart()) - 1,
+ seq.findIndex(seq.getEnd()) - 1 }),
+ Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
+
+ }
+
+ @Test(groups = { "Functional" })
+ public void testLocateVisibleBoundsPathologicals()
+ {
+ // test some pathological cases we missed
+ AlignmentI al = new Alignment(new SequenceI[] { new Sequence(
+ "refseqGaptest", "KTDVTI----------NFI-----G----L") });
+ HiddenColumns cs = new HiddenColumns();
+ cs.hideInsertionsFor(al.getSequenceAt(0));
+ assertEquals(
+ "G",
+ ""
+ + al.getSequenceAt(0).getCharAt(
+ cs.adjustForHiddenColumns(9)));
+
+ }
+
+ @Test(groups = { "Functional" })
+ public void testHideColumns()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ AlignmentI al = gen.generate(50, 20, 123, 5, 5);
+
+ ColumnSelection colsel = new ColumnSelection();
+ HiddenColumns cs = al.getHiddenColumns();
+ colsel.hideSelectedColumns(5, al.getHiddenColumns());
+ List<int[]> hidden = cs.getHiddenRegions();
+ assertEquals(1, hidden.size());
+ assertEquals("[5, 5]", Arrays.toString(hidden.get(0)));
+
+ colsel.hideSelectedColumns(3, al.getHiddenColumns());
+ assertEquals(2, hidden.size());
+ // two hidden ranges, in order:
+ assertSame(hidden, cs.getHiddenRegions());
+ assertEquals("[3, 3]", Arrays.toString(hidden.get(0)));
+ assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
+
+ // hiding column 4 expands [3, 3] to [3, 4]
+ // and merges to [5, 5] to make [3, 5]
+ colsel.hideSelectedColumns(4, al.getHiddenColumns());
+ hidden = cs.getHiddenRegions();
+ assertEquals(1, hidden.size());
+ assertEquals("[3, 5]", Arrays.toString(hidden.get(0)));
+
+ // clear hidden columns (note they are added to selected)
+ cs.revealAllHiddenColumns(colsel);
+ // it is now actually null but getter returns an empty list
+ assertTrue(cs.getHiddenRegions().isEmpty());
+
+ cs.hideColumns(3, 6);
+ hidden = cs.getHiddenRegions();
+ int[] firstHiddenRange = hidden.get(0);
+ assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
+
+ // adding a subrange of already hidden should do nothing
+ cs.hideColumns(4, 5);
+ assertEquals(1, hidden.size());
+ assertSame(firstHiddenRange, cs.getHiddenRegions().get(0));
+ cs.hideColumns(3, 5);
+ assertEquals(1, hidden.size());
+ assertSame(firstHiddenRange, cs.getHiddenRegions().get(0));
+ cs.hideColumns(4, 6);
+ assertEquals(1, hidden.size());
+ assertSame(firstHiddenRange, cs.getHiddenRegions().get(0));
+ cs.hideColumns(3, 6);
+ assertEquals(1, hidden.size());
+ assertSame(firstHiddenRange, cs.getHiddenRegions().get(0));
+
+ cs.revealAllHiddenColumns(colsel);
+ cs.hideColumns(2, 4);
+ hidden = cs.getHiddenRegions();
+ assertEquals(1, hidden.size());
+ assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
+
+ // extend contiguous with 2 positions overlap
+ cs.hideColumns(3, 5);
+ assertEquals(1, hidden.size());
+ assertEquals("[2, 5]", Arrays.toString(hidden.get(0)));
+
+ // extend contiguous with 1 position overlap
+ cs.hideColumns(5, 6);
+ assertEquals(1, hidden.size());
+ assertEquals("[2, 6]", Arrays.toString(hidden.get(0)));
+
+ // extend contiguous with overlap both ends:
+ cs.hideColumns(1, 7);
+ assertEquals(1, hidden.size());
+ assertEquals("[1, 7]", Arrays.toString(hidden.get(0)));
+ }
+
+ /**
+ * Test the method that reveals a range of hidden columns given the start
+ * column of the range
+ */
+ @Test(groups = { "Functional" })
+ public void testRevealHiddenColumns()
+ {
+ ColumnSelection colsel = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
+ cs.hideColumns(5, 8);
+ colsel.addElement(10);
+ cs.revealHiddenColumns(5, colsel);
+ // hidden columns list now null but getter returns empty list:
+ assertTrue(cs.getHiddenRegions().isEmpty());
+ // revealed columns are marked as selected (added to selection):
+ assertEquals("[10, 5, 6, 7, 8]", colsel.getSelected().toString());
+
+ // calling with a column other than the range start does nothing:
+ colsel = new ColumnSelection();
+ cs = new HiddenColumns();
+ cs.hideColumns(5, 8);
+ List<int[]> hidden = cs.getHiddenRegions();
+ cs.revealHiddenColumns(6, colsel);
+ assertSame(hidden, cs.getHiddenRegions());
+ assertTrue(colsel.getSelected().isEmpty());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testRevealAllHiddenColumns()
+ {
+ HiddenColumns cs = new HiddenColumns();
+ ColumnSelection colsel = new ColumnSelection();
+ cs.hideColumns(5, 8);
+ cs.hideColumns(2, 3);
+ colsel.addElement(11);
+ colsel.addElement(1);
+ cs.revealAllHiddenColumns(colsel);
+
+ /*
+ * revealing hidden columns adds them (in order) to the (unordered)
+ * selection list
+ */
+ assertTrue(cs.getHiddenRegions().isEmpty());
+ assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]", colsel.getSelected()
+ .toString());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testIsVisible()
+ {
+ HiddenColumns cs = new HiddenColumns();
+ cs.hideColumns(2, 4);
+ cs.hideColumns(6, 7);
+ assertTrue(cs.isVisible(0));
+ assertTrue(cs.isVisible(-99));
+ assertTrue(cs.isVisible(1));
+ assertFalse(cs.isVisible(2));
+ assertFalse(cs.isVisible(3));
+ assertFalse(cs.isVisible(4));
+ assertTrue(cs.isVisible(5));
+ assertFalse(cs.isVisible(6));
+ assertFalse(cs.isVisible(7));
+ }
+
+ /**
+ * Test for the case when a hidden range encloses more one already hidden
+ * range
+ */
+ @Test(groups = { "Functional" })
+ public void testHideColumns_subsumingHidden()
+ {
+ /*
+ * JAL-2370 bug scenario:
+ * two hidden ranges subsumed by a third
+ */
+ HiddenColumns cs = new HiddenColumns();
+ cs.hideColumns(49, 59);
+ cs.hideColumns(69, 79);
+ List<int[]> hidden = cs.getHiddenRegions();
+ assertEquals(2, hidden.size());
+ assertEquals("[49, 59]", Arrays.toString(hidden.get(0)));
+ assertEquals("[69, 79]", Arrays.toString(hidden.get(1)));
+
+ cs.hideColumns(48, 80);
+ hidden = cs.getHiddenRegions();
+ assertEquals(1, hidden.size());
+ assertEquals("[48, 80]", Arrays.toString(hidden.get(0)));
+
+ /*
+ * another...joining hidden ranges
+ */
+ cs = new HiddenColumns();
+ cs.hideColumns(10, 20);
+ cs.hideColumns(30, 40);
+ cs.hideColumns(50, 60);
+ // hiding 21-49 should merge to one range
+ cs.hideColumns(21, 49);
+ hidden = cs.getHiddenRegions();
+ assertEquals(1, hidden.size());
+ assertEquals("[10, 60]", Arrays.toString(hidden.get(0)));
+
+ /*
+ * another...left overlap, subsumption, right overlap,
+ * no overlap of existing hidden ranges
+ */
+ cs = new HiddenColumns();
+ cs.hideColumns(10, 20);
+ cs.hideColumns(10, 20);
+ cs.hideColumns(30, 35);
+ cs.hideColumns(40, 50);
+ cs.hideColumns(60, 70);
+
+ cs.hideColumns(15, 45);
+ hidden = cs.getHiddenRegions();
+ assertEquals(2, hidden.size());
+ assertEquals("[10, 50]", Arrays.toString(hidden.get(0)));
+ assertEquals("[60, 70]", Arrays.toString(hidden.get(1)));
+ }
+
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertTrue;
+
+import java.util.NoSuchElementException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class VisibleColsIteratorTest
+{
+ HiddenColumns hiddenCols;
+
+ HiddenColumns hiddenColsAtStart;
+
+ @BeforeClass(groups = { "Functional" })
+ public void setup()
+ {
+ hiddenCols = new HiddenColumns();
+ hiddenCols.hideColumns(2, 4);
+
+ hiddenColsAtStart = new HiddenColumns();
+ hiddenColsAtStart.hideColumns(0, 2);
+ }
+
+ /*
+ * Test iterator iterates correctly through the columns
+ * when alignment has hidden cols
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNextWithHidden()
+ {
+ VisibleColsIterator it = new VisibleColsIterator(0, 6, hiddenCols);
+ int count = 0;
+ while (it.hasNext())
+ {
+ it.next();
+ count++;
+ }
+ assertTrue(count == 4, "hasNext() is false after 4 iterations");
+ }
+
+ /*
+ * Test iterator iterates correctly through the columns
+ * when alignment has no hidden cols
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNextNoHidden()
+ {
+ VisibleColsIterator it2 = new VisibleColsIterator(0, 3,
+ new HiddenColumns());
+ int count = 0;
+ while (it2.hasNext())
+ {
+ it2.next();
+ count++;
+ }
+ assertTrue(count == 4, "hasNext() is false after 4 iterations");
+ }
+
+ /*
+ * Test iterator iterates correctly through the columns
+ * when alignment has hidden cols at start
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNextStartHidden()
+ {
+ VisibleColsIterator it3 = new VisibleColsIterator(0, 6,
+ hiddenColsAtStart);
+ int count = 0;
+ while (it3.hasNext())
+ {
+ it3.next();
+ count++;
+ }
+ assertTrue(count == 4, "hasNext() is false after 4 iterations");
+ }
+
+ /*
+ * Test iterator iterates correctly through the columns
+ * when alignment has hidden cols at end
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNextEndHidden()
+ {
+ VisibleColsIterator it4 = new VisibleColsIterator(0, 4, hiddenCols);
+ int count = 0;
+ while (it4.hasNext())
+ {
+ it4.next();
+ count++;
+ }
+ assertTrue(count == 2, "hasNext() is false after 2 iterations");
+
+ }
+
+ /*
+ * Test iterator always throws NoSuchElementException at end of iteration
+ * when alignment has hidden cols
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNextWithHidden() throws NoSuchElementException
+ {
+ VisibleColsIterator it = new VisibleColsIterator(0, 3, hiddenCols);
+ while (it.hasNext())
+ {
+ it.next();
+ }
+ it.next();
+ }
+
+ /*
+ * Test iterator always throws NoSuchElementException at end of iteration
+ * when alignment has no hidden cols
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNextNoHidden() throws NoSuchElementException
+ {
+ VisibleColsIterator it2 = new VisibleColsIterator(0, 3,
+ new HiddenColumns());
+ while (it2.hasNext())
+ {
+ it2.next();
+ }
+ it2.next();
+ }
+
+ /*
+ * Test iterator always throws NoSuchElementException at end of iteration
+ * when alignment has hidden cols at start
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNextStartHidden() throws NoSuchElementException
+ {
+ VisibleColsIterator it3 = new VisibleColsIterator(0, 6,
+ hiddenColsAtStart);
+ while (it3.hasNext())
+ {
+ it3.next();
+ }
+ it3.next();
+ }
+
+ /*
+ * Test iterator always throws NoSuchElementException at end of iteration
+ * when alignment has hidden cols at end
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNextEndHidden() throws NoSuchElementException
+ {
+ VisibleColsIterator it4 = new VisibleColsIterator(0, 4, hiddenCols);
+ while (it4.hasNext())
+ {
+ it4.next();
+ }
+ it4.next();
+ }
+
+ /*
+ * Test calls to remove throw UnsupportedOperationException
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { UnsupportedOperationException.class })
+ public void testRemove() throws UnsupportedOperationException
+ {
+ VisibleColsIterator it = new VisibleColsIterator(0, 3, hiddenCols);
+ it.remove();
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.datamodel;
+
+import static org.testng.Assert.assertTrue;
+
+import jalview.analysis.AlignmentGenerator;
+
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class VisibleRowsIteratorTest
+{
+ AlignmentI al;
+
+ AlignmentI al2;
+
+ AlignmentI al3;
+
+ Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
+
+ Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences2 = new Hashtable<SequenceI, SequenceCollectionI>();
+
+ @BeforeClass(groups = { "Functional" })
+ public void setup()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ al = gen.generate(20, 15, 123, 5, 5);
+ if (!hiddenRepSequences.isEmpty())
+ {
+ al.getHiddenSequences().showAll(hiddenRepSequences);
+ }
+ hideSequences(al, hiddenRepSequences, 2, 4);
+
+ al2 = gen.generate(20, 15, 123, 5, 5);
+ if (!hiddenRepSequences2.isEmpty())
+ {
+ al2.getHiddenSequences().showAll(hiddenRepSequences2);
+ }
+ hideSequences(al2, hiddenRepSequences2, 0, 2);
+
+ al3 = gen.generate(20, 15, 123, 5, 5);
+ }
+
+ /*
+ * Test iterator iterates correctly through the rows
+ * when alignment has hidden rows
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNextWithHidden()
+ {
+ VisibleRowsIterator it = new VisibleRowsIterator(0, 6, al);
+ int count = 0;
+ while (it.hasNext())
+ {
+ it.next();
+ count++;
+ }
+ assertTrue(count == 4, "hasNext() is false after 4 iterations");
+ }
+
+ /*
+ * Test iterator iterates correctly through the rows
+ * when alignment has no hidden rows
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNextNoHidden()
+ {
+ VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al3);
+ int count = 0;
+ while (it.hasNext())
+ {
+ it.next();
+ count++;
+ }
+ assertTrue(count == 4, "hasNext() is false after 4 iterations");
+ }
+
+ /*
+ * Test iterator iterates correctly through the rows
+ * when alignment has hidden rows at start
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNextStartHidden()
+ {
+ VisibleRowsIterator it = new VisibleRowsIterator(0, 6, al2);
+ int count = 0;
+ while (it.hasNext())
+ {
+ it.next();
+ count++;
+ }
+ assertTrue(count == 4, "hasNext() is false after 4 iterations");
+ }
+
+ /*
+ * Test iterator iterates correctly through the rows
+ * when alignment has hidden rows at end
+ */
+ @Test(groups = { "Functional" })
+ public void testHasNextAndNextEndHidden()
+ {
+ VisibleRowsIterator it = new VisibleRowsIterator(0, 4, al);
+ int count = 0;
+ while (it.hasNext())
+ {
+ it.next();
+ count++;
+ }
+ assertTrue(count == 2, "hasNext() is false after 2 iterations");
+ }
+
+ /*
+ * Test iterator always throws NoSuchElementException at end of iteration
+ * when alignment has hidden rows
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNextWithHidden() throws NoSuchElementException
+ {
+ VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al);
+ while (it.hasNext())
+ {
+ it.next();
+ }
+ it.next();
+ }
+
+ /*
+ * Test iterator always throws NoSuchElementException at end of iteration
+ * when alignment has no hidden rows
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNextNoHidden() throws NoSuchElementException
+ {
+ VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al3);
+ while (it.hasNext())
+ {
+ it.next();
+ }
+ it.next();
+ }
+
+ /*
+ * Test iterator always throws NoSuchElementException at end of iteration
+ * when alignment has hidden rows at start
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNextStartHidden() throws NoSuchElementException
+ {
+ VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al2);
+ while (it.hasNext())
+ {
+ it.next();
+ }
+ it.next();
+ }
+
+ /*
+ * Test iterator always throws NoSuchElementException at end of iteration
+ * when alignment has hidden rows at end
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { NoSuchElementException.class })
+ public void testLastNextEndHidden() throws NoSuchElementException
+ {
+ VisibleRowsIterator it = new VisibleRowsIterator(0, 4, al);
+ while (it.hasNext())
+ {
+ it.next();
+ }
+ it.next();
+ }
+
+ /*
+ * Test calls to remove throw UnsupportedOperationException
+ */
+ @Test(
+ groups = { "Functional" },
+ expectedExceptions = { UnsupportedOperationException.class })
+ public void testRemove() throws UnsupportedOperationException
+ {
+ VisibleRowsIterator it = new VisibleRowsIterator(0, 3, al);
+ it.remove();
+ }
+
+ /*
+ * Hide sequences between start and end
+ */
+ private void hideSequences(AlignmentI alignment,
+ Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences,
+ int start, int end)
+ {
+ SequenceI[] allseqs = alignment.getSequencesArray();
+ SequenceGroup theseSeqs = new SequenceGroup();
+
+ for (int i = start; i <= end; i++)
+ {
+ theseSeqs.addSequence(allseqs[i], false);
+ alignment.getHiddenSequences().hideSequence(allseqs[i]);
+ }
+
+ hiddenRepSequences.put(allseqs[start], theseSeqs);
+ }
+}
*/
assertFalse(alignFrame.hideFeatureColumns("exon", true));
assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
- assertTrue(alignFrame.getViewport().getColumnSelection().getHiddenColumns()
+ assertTrue(alignFrame.getViewport().getAlignment().getHiddenColumns()
+ .getHiddenRegions()
.isEmpty());
assertFalse(alignFrame.hideFeatureColumns("exon", false));
assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
- assertTrue(alignFrame.getViewport().getColumnSelection().getHiddenColumns()
+ assertTrue(alignFrame.getViewport().getAlignment().getHiddenColumns()
+ .getHiddenRegions()
.isEmpty());
/*
*/
assertFalse(alignFrame.hideFeatureColumns("Metal", true));
assertTrue(alignFrame.getViewport().getColumnSelection().isEmpty());
- List<int[]> hidden = alignFrame.getViewport().getColumnSelection()
- .getHiddenColumns();
+ List<int[]> hidden = alignFrame.getViewport().getAlignment()
+ .getHiddenColumns()
+ .getHiddenRegions();
assertTrue(hidden.isEmpty());
/*
* [1-3], [6-8] base zero
*/
assertTrue(alignFrame.hideFeatureColumns("Turn", true));
- hidden = alignFrame.getViewport().getColumnSelection().getHiddenColumns();
+ hidden = alignFrame.getViewport().getAlignment().getHiddenColumns()
+ .getHiddenRegions();
assertEquals(hidden.size(), 2);
assertEquals(hidden.get(0)[0], 1);
assertEquals(hidden.get(0)[1], 3);
import java.util.ArrayList;
import java.util.List;
+import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
Boolean.TRUE.toString());
Cache.applicationProperties.setProperty("SHOW_CONSERVATION",
Boolean.FALSE.toString());
+ Cache.applicationProperties.setProperty("SHOW_OCCUPANCY",
+ Boolean.FALSE.toString());
Cache.applicationProperties.setProperty("SHOW_IDENTITY",
Boolean.FALSE.toString());
AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
av.setSelectionGroup(sg2);
assertSame(sg2.getContext(), sg1); // unchanged
}
+ /**
+ * Verify that setting/clearing SHOW_OCCUPANCY preference adds or omits occupancy row from viewport
+ */
+ @Test(groups = { "Functional" })
+ public void testShowOrDontShowOccupancy()
+ {
+ // disable occupancy
+ jalview.bin.Cache.setProperty("SHOW_OCCUPANCY", Boolean.FALSE.toString());
+ AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+ "examples/uniref50.fa", DataSourceType.FILE);
+ AlignViewport av = af.getViewport();
+ Assert.assertNull(av.getAlignmentGapAnnotation(), "Preference did not disable occupancy row.");
+ int c = 0;
+ for (AlignmentAnnotation aa : av.getAlignment().findAnnotations(null,
+ null, "Occupancy"))
+ {
+ c++;
+ }
+ Assert.assertEquals(c, 0, "Expected zero occupancy rows.");
+
+ // enable occupancy
+ jalview.bin.Cache.setProperty("SHOW_OCCUPANCY", Boolean.TRUE.toString());
+ af = new FileLoader().LoadFileWaitTillLoaded(
+ "examples/uniref50.fa", DataSourceType.FILE);
+ av = af.getViewport();
+ Assert.assertNotNull(av.getAlignmentGapAnnotation(), "Preference did not enable occupancy row.");
+ c = 0;
+ for (AlignmentAnnotation aa : av.getAlignment().findAnnotations(null,
+ null, av.getAlignmentGapAnnotation().label))
+ {
+ c++;
+ }
+ ;
+ Assert.assertEquals(c, 1, "Expected to find one occupancy row.");
+
+ }
}
assertEquals(Color.magenta, sr.getResidueBoxColour(seq, 5)); // G
assertEquals(Color.orange, sr.getResidueBoxColour(seq, 12)); // F
}
+
+ @Test(groups = { "Functional" })
+ public void testGetResidueBoxColour_none()
+ {
+ SequenceI seq = new Sequence("name", "MA--TVLGSPRAPAFF");
+ AlignmentI al = new Alignment(new SequenceI[] { seq });
+ final AlignViewport av = new AlignViewport(al);
+ SequenceRenderer sr = new SequenceRenderer(av);
+
+ assertEquals(Color.white, sr.getResidueBoxColour(seq, 0));
+ assertEquals(Color.white, sr.getResidueBoxColour(seq, 2));
+
+ // set for overview
+ sr.forOverview = true;
+ assertEquals(Color.lightGray, sr.getResidueBoxColour(seq, 0));
+ assertEquals(Color.white, sr.getResidueBoxColour(seq, 2));
+ }
+
// TODO more tests for getResidueBoxColour covering groups, feature rendering,
// gaps, overview...
assertEquals("Cached PDB Entries", filterOpt.getName());
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void fetchStructuresInfoTest()
{
SequenceI[] selectedSeqs = new SequenceI[] { seq };
import static org.testng.AssertJUnit.assertTrue;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.gui.JvOptionPane;
import jalview.io.AnnotationFile.ViewDef;
try
{
AlignmentI al = readAlignmentFile(f);
- ColumnSelection cs = new ColumnSelection();
+ HiddenColumns cs = new HiddenColumns();
assertTrue(
"Test "
+ testname
DataSourceType.FILE));
AnnotationFile aff = new AnnotationFile();
+ // ViewDef is not used by Jalview
ViewDef v = aff.new ViewDef(null, al.getHiddenSequences(), cs,
new Hashtable());
String anfileout = new AnnotationFile().printAnnotations(
DataSourceType.PASTE));
// test for consistency in io
- StockholmFileTest.testAlignmentEquivalence(al, al_new, false);
+ StockholmFileTest.testAlignmentEquivalence(al, al_new, false, false,
+ false);
return;
} catch (Exception e)
{
{
"examples/testdata/cullpdb_pc25_res3.0_R0.3_d150729_chains9361.fasta.15316",
FileFormat.Fasta },
-
+ { "resources/scoreModel/pam250.scm", FileFormat.ScoreMatrix },
+ { "resources/scoreModel/blosum80.scm", FileFormat.ScoreMatrix }
// { "examples/testdata/test.amsa", "AMSA" },
// { "examples/test.jnet", "JnetFile" },
};
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.Annotation;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceGroup;
import jalview.gui.JvOptionPane;
import jalview.json.binding.biojson.v1.ColourSchemeMapper;
import jalview.schemes.ColourSchemeI;
+import jalview.schemes.ResidueColourScheme;
import java.io.IOException;
import java.util.ArrayList;
private HashMap<String, SequenceGroup> expectedGrps = new HashMap<String, SequenceGroup>();
- private ColumnSelection expectedColSel = new ColumnSelection();
+ private HiddenColumns expectedColSel = new HiddenColumns();
private SequenceI[] expectedHiddenSeqs = new SequenceI[1];
private JSONFile jf;
+ private AlignExportSettingI exportSettings;
+
@BeforeTest(alwaysRun = true)
public void setup() throws Exception
{
expectedSeqs.put(seq.getName(), seq);
}
- // create and add sequence groups
- ArrayList<SequenceI> grpSeqs = new ArrayList<SequenceI>();
+ // create and add a sequence group
+ List<SequenceI> grpSeqs = new ArrayList<SequenceI>();
grpSeqs.add(seqs[1]);
grpSeqs.add(seqs[2]);
grpSeqs.add(seqs[3]);
grpSeqs.add(seqs[4]);
- SequenceGroup seqGrp = new SequenceGroup(grpSeqs, "JGroup:1883305585",
+ SequenceGroup seqGrp = new SequenceGroup(grpSeqs,
+ "JGroup:1883305585",
null, true, true, false, 21, 29);
ColourSchemeI scheme = ColourSchemeMapper.getJalviewColourScheme(
"zappo", seqGrp);
TEST_SEQ_HEIGHT = expectedSeqs.size();
TEST_GRP_HEIGHT = expectedGrps.size();
TEST_ANOT_HEIGHT = expectedAnnots.size();
- TEST_CS_HEIGHT = expectedColSel.getHiddenColumns().size();
+ TEST_CS_HEIGHT = expectedColSel.getHiddenRegions().size();
- AlignExportSettingI exportSettings = new AlignExportSettingI()
+ exportSettings = new AlignExportSettingI()
{
@Override
public boolean isExportHiddenSequences()
jf = (JSONFile) formatAdapter.getAlignFile();
AlignFrame af = new AlignFrame(alignment, jf.getHiddenSequences(),
- jf.getColumnSelection(), AlignFrame.DEFAULT_WIDTH,
+ jf.getHiddenColumns(), AlignFrame.DEFAULT_WIDTH,
AlignFrame.DEFAULT_HEIGHT);
af.getViewport().setShowSequenceFeatures(jf.isShowSeqFeatures());
String colourSchemeName = jf.getGlobalColourScheme();
@Test(groups = { "Functional" })
public void hiddenColsTest()
{
- ColumnSelection cs = testJsonFile.getColumnSelection();
+ HiddenColumns cs = testJsonFile.getHiddenColumns();
Assert.assertNotNull(cs);
- Assert.assertNotNull(cs.getHiddenColumns());
- List<int[]> hiddenCols = cs.getHiddenColumns();
+ Assert.assertNotNull(cs.getHiddenRegions());
+ List<int[]> hiddenCols = cs.getHiddenRegions();
Assert.assertEquals(hiddenCols.size(), TEST_CS_HEIGHT);
Assert.assertEquals(hiddenCols.get(0), expectedColSel
- .getHiddenColumns().get(0),
+ .getHiddenRegions().get(0),
"Mismatched hidden columns!");
}
"Zappo colour scheme expected!");
}
+ /**
+ * Test for bug JAL-2489, NPE when exporting BioJSON with global colour
+ * scheme, and a group colour scheme, set as 'None'
+ */
+ @Test(groups = { "Functional" })
+ public void testBioJSONRoundTripWithColourSchemeNone()
+ {
+ AppletFormatAdapter formatAdapter = new AppletFormatAdapter();
+
+ Alignment _alignment;
+ try
+ {
+ // load example BioJSON file
+ _alignment = (Alignment) formatAdapter.readFile(TEST_JSON_FILE,
+ DataSourceType.FILE, FileFormat.Json);
+ JSONFile bioJsonFile = (JSONFile) formatAdapter.getAlignFile();
+ AlignFrame alignFrame = new AlignFrame(_alignment,
+ bioJsonFile.getHiddenSequences(),
+ bioJsonFile.getHiddenColumns(), AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT);
+
+ /*
+ * Create a group on the alignment;
+ * Change global and group colour scheme to 'None' and perform round trip
+ */
+ SequenceGroup sg = new SequenceGroup();
+ sg.addSequence(_alignment.getSequenceAt(0), false);
+ sg.setColourScheme(null);
+ ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
+ ResidueColourScheme.NONE, _alignment);
+ alignFrame.changeColour(cs);
+ alignFrame.getViewport().setFeaturesDisplayed(
+ bioJsonFile.getDisplayedFeatures());
+ formatAdapter = new AppletFormatAdapter(alignFrame.alignPanel,
+ exportSettings);
+ // export BioJSON string
+ String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
+ alignFrame.alignPanel.getAlignment(), false);
+ // read back Alignment from BioJSON string
+ formatAdapter = new AppletFormatAdapter();
+ formatAdapter.readFile(jsonOutput, DataSourceType.PASTE,
+ FileFormat.Json);
+ // assert 'None' colour scheme is retained after round trip
+ JSONFile _bioJsonFile = (JSONFile) formatAdapter.getAlignFile();
+ Assert.assertEquals(_bioJsonFile.getGlobalColourScheme(),
+ ResidueColourScheme.NONE);
+ } catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
@Test(groups = { "Functional" })
public void isShowSeqFeaturesSet()
{
// System.out.println(">>>>>>>>>>>>>> features matched : " + matched);
return matched;
}
+
+ /**
+ * Test group roundtrip with null (None) group colour scheme
+ *
+ * @throws IOException
+ */
+ @Test(groups = { "Functional" })
+ public void testGrpParsed_colourNone() throws IOException
+ {
+ AlignmentI copy = new Alignment(testAlignment);
+ SequenceGroup sg = testAlignment.getGroups().get(0);
+ SequenceGroup copySg = new SequenceGroup(new ArrayList<SequenceI>(),
+ sg.getName(),
+ null, sg.getDisplayBoxes(), sg.getDisplayText(),
+ sg.getColourText(), sg.getStartRes(), sg.getEndRes());
+ for (SequenceI seq : sg.getSequences())
+ {
+ int seqIndex = testAlignment.findIndex(seq);
+ copySg.addSequence(copy.getSequenceAt(seqIndex), false);
+ }
+ copy.addGroup(copySg);
+
+ AlignFrame af = new AlignFrame(copy, copy.getWidth(), copy.getHeight());
+ AppletFormatAdapter formatAdapter = new AppletFormatAdapter(
+ af.alignPanel);
+ String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
+ copy, false);
+ formatAdapter = new AppletFormatAdapter();
+ AlignmentI newAlignment = formatAdapter.readFile(jsonOutput,
+ DataSourceType.PASTE, FileFormat.Json);
+
+ Assert.assertNotNull(newAlignment.getGroups());
+ for (SequenceGroup seqGrp : newAlignment.getGroups())
+ {
+ SequenceGroup expectedGrp = expectedGrps.get(seqGrp.getName());
+ AssertJUnit.assertTrue(
+ "Failed SequenceGroup Test for >>> " + seqGrp.getName(),
+ isGroupMatched(expectedGrp, seqGrp));
+ passedCount++;
+ }
+ AssertJUnit.assertEquals("Some SequenceGroups did not pass the test",
+ TEST_GRP_HEIGHT, passedCount);
+ }
}
import static org.testng.ConversionUtils.wrapDataProvider;
-import jalview.analysis.NJTree;
import jalview.analysis.SequenceIdMatcher;
+import jalview.analysis.TreeModel;
import jalview.datamodel.SequenceI;
import jalview.datamodel.SequenceNode;
import jalview.gui.JvOptionPane;
stage = "Compare original and generated tree" + treename;
Vector<SequenceNode> oseqs, nseqs;
- oseqs = new NJTree(new SequenceI[0], nf).findLeaves(nf.getTree());
+ oseqs = new TreeModel(new SequenceI[0], null, nf).findLeaves(nf
+ .getTree());
AssertJUnit.assertTrue(stage + "No nodes in original tree.",
oseqs.size() > 0);
SequenceI[] olsqs = new SequenceI[oseqs.size()];
{
olsqs[i] = (SequenceI) oseqs.get(i).element();
}
- nseqs = new NJTree(new SequenceI[0], nf_regen).findLeaves(nf_regen
+ nseqs = new TreeModel(new SequenceI[0], null, nf_regen)
+ .findLeaves(nf_regen
.getTree());
AssertJUnit.assertTrue(stage + "No nodes in regerated tree.",
nseqs.size() > 0);
DataSourceType.PASTE, FileFormat.Phylip);
assertNotNull("Couldn't parse reimported alignment data.", al_input);
- StockholmFileTest.testAlignmentEquivalence(al, al_input, false);
+ StockholmFileTest.testAlignmentEquivalence(al, al_input, false, false,
+ false);
}
}
{
StockholmFileTest.testFileIOwithFormat(new File(
"examples/testdata/rna-alignment.xml"), FileFormat.Stockholm,
- -1, -1);
+ -1, -1, true, true, true);
}
--- /dev/null
+package jalview.io;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import jalview.analysis.scoremodels.ScoreMatrix;
+import jalview.analysis.scoremodels.ScoreModels;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import org.testng.annotations.Test;
+
+public class ScoreMatrixFileTest
+{
+
+ /**
+ * Test a successful parse of a (small) score matrix file
+ *
+ * @throws IOException
+ * @throws MalformedURLException
+ */
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiMixedDelimiters()
+ throws MalformedURLException,
+ IOException
+ {
+ /*
+ * some messy but valid input data, with comma, space
+ * or tab (or combinations) as score value delimiters
+ * this example includes 'guide' symbols on score rows
+ */
+ String data = "ScoreMatrix MyTest (example)\n" + "A\tT\tU\tt\tx\t-\n"
+ + "A,1.1,1.2,1.3,1.4, 1.5, 1.6\n"
+ + "T,2.1 2.2 2.3 2.4 2.5 2.6\n"
+ + "U\t3.1\t3.2\t3.3\t3.4\t3.5\t3.6\t\n"
+ + "t, 5.1,5.3,5.3,5.4,5.5, 5.6\n"
+ + "x\t6.1, 6.2 6.3 6.4 6.5 6.6\n"
+ + "-, \t7.1\t7.2 7.3, 7.4, 7.5\t,7.6\n";
+ FileParse fp = new FileParse(data, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ ScoreMatrix sm = parser.parseMatrix();
+
+ assertNotNull(sm);
+ assertEquals(sm.getName(), "MyTest (example)");
+ assertEquals(sm.getSize(), 6);
+ assertNull(sm.getDescription());
+ assertTrue(sm.isDNA());
+ assertFalse(sm.isProtein());
+ assertEquals(sm.getMinimumScore(), 1.1f);
+ assertEquals(sm.getPairwiseScore('A', 'A'), 1.1f);
+ assertEquals(sm.getPairwiseScore('A', 'T'), 1.2f);
+ assertEquals(sm.getPairwiseScore('a', 'T'), 1.2f); // A/a equivalent
+ assertEquals(sm.getPairwiseScore('A', 't'), 1.4f); // T/t not equivalent
+ assertEquals(sm.getPairwiseScore('a', 't'), 1.4f);
+ assertEquals(sm.getPairwiseScore('U', 'x'), 3.5f);
+ assertEquals(sm.getPairwiseScore('u', 'x'), 3.5f);
+ // X (upper) and '.' unmapped - get minimum score
+ assertEquals(sm.getPairwiseScore('U', 'X'), 1.1f);
+ assertEquals(sm.getPairwiseScore('A', '.'), 1.1f);
+ assertEquals(sm.getPairwiseScore('-', '-'), 7.6f);
+ assertEquals(sm.getPairwiseScore('A', (char) 128), 0f); // out of range
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_headerMissing()
+ {
+ String data;
+
+ data = "X Y\n1 2\n3 4\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Format error: 'ScoreMatrix <name>' should be the first non-comment line");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiNotEnoughRows()
+ {
+ String data = "ScoreMatrix MyTest\nX Y Z\n1 2 3\n4 5 6\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Expected 3 rows of score data in score matrix but only found 2");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiNotEnoughColumns()
+ {
+ String data = "ScoreMatrix MyTest\nX Y Z\n1 2 3\n4 5\n7 8 9\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Expected 3 scores at line 4: '4 5' but found 2");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiTooManyColumns()
+ {
+ /*
+ * with two too many columns:
+ */
+ String data = "ScoreMatrix MyTest\nX\tY\tZ\n1 2 3\n4 5 6 7\n8 9 10\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Expected 3 scores at line 4: '4 5 6 7' but found 4");
+ }
+
+ /*
+ * with guide character and one too many columns:
+ */
+ data = "ScoreMatrix MyTest\nX Y\nX 1 2\nY 3 4 5\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Expected 2 scores at line 4: 'Y 3 4 5' but found 3");
+ }
+
+ /*
+ * with no guide character and one too many columns
+ */
+ data = "ScoreMatrix MyTest\nX Y\n1 2\n3 4 5\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Expected 2 scores at line 4: '3 4 5' but found 3");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiTooManyRows()
+ {
+ String data = "ScoreMatrix MyTest\n\tX\tY\tZ\n1 2 3\n4 5 6\n7 8 9\n10 11 12\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Unexpected extra input line in score model file: '10 11 12'");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiBadDelimiter()
+ {
+ String data = "ScoreMatrix MyTest\n X Y Z\n1|2|3\n4|5|6\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Invalid score value '1|2|3' at line 3 column 0");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiBadFloat()
+ {
+ String data = "ScoreMatrix MyTest\n\tX\tY\tZ\n1 2 3\n4 five 6\n7 8 9\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Invalid score value 'five' at line 4 column 1");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiBadGuideCharacter()
+ {
+ String data = "ScoreMatrix MyTest\n\tX Y\nX 1 2\ny 3 4\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Error parsing score matrix at line 4, expected 'Y' but found 'y'");
+ }
+
+ data = "ScoreMatrix MyTest\n\tX Y\nXX 1 2\nY 3 4\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Error parsing score matrix at line 3, expected 'X' but found 'XX'");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiNameMissing()
+ {
+ /*
+ * Name missing on ScoreMatrix header line
+ */
+ String data = "ScoreMatrix\nX Y\n1 2\n3 4\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(
+ e.getMessage(),
+ "Format error: expected 'ScoreMatrix <name>', found 'ScoreMatrix' at line 1");
+ }
+ }
+
+ /**
+ * Test a successful parse of a (small) score matrix file
+ *
+ * @throws IOException
+ * @throws MalformedURLException
+ */
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiFormat() throws MalformedURLException,
+ IOException
+ {
+ // input including comment and blank lines
+ String data = "ScoreMatrix MyTest\n#comment\n\n" + "\tA\tB\tC\n"
+ + "A\t1.0\t2.0\t3.0\n" + "B\t4.0\t5.0\t6.0\n"
+ + "C\t7.0\t8.0\t9.0\n";
+ FileParse fp = new FileParse(data, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ ScoreMatrix sm = parser.parseMatrix();
+
+ assertNotNull(sm);
+ assertEquals(sm.getName(), "MyTest");
+ assertEquals(parser.getMatrixName(), "MyTest");
+ assertEquals(sm.getPairwiseScore('A', 'A'), 1.0f);
+ assertEquals(sm.getPairwiseScore('B', 'c'), 6.0f);
+ assertEquals(sm.getSize(), 3);
+ }
+
+ /**
+ * Test a successful parse of a (small) score matrix file
+ *
+ * @throws IOException
+ * @throws MalformedURLException
+ */
+ @Test(groups = "Functional")
+ public void testParseMatrix_aaIndexBlosum80()
+ throws MalformedURLException,
+ IOException
+ {
+ FileParse fp = new FileParse("resources/scoreModel/blosum80.scm",
+ DataSourceType.FILE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ ScoreMatrix sm = parser.parseMatrix();
+
+ assertNotNull(sm);
+ assertEquals(sm.getName(), "HENS920103");
+ assertEquals(sm.getDescription(),
+ "BLOSUM80 substitution matrix (Henikoff-Henikoff, 1992)");
+ assertFalse(sm.isDNA());
+ assertTrue(sm.isProtein());
+ assertEquals(20, sm.getSize());
+
+ assertEquals(sm.getPairwiseScore('A', 'A'), 7f);
+ assertEquals(sm.getPairwiseScore('A', 'R'), -3f);
+ assertEquals(sm.getPairwiseScore('r', 'a'), -3f); // A/a equivalent
+ }
+
+ /**
+ * Test a successful parse of a (small) score matrix file
+ *
+ * @throws IOException
+ * @throws MalformedURLException
+ */
+ @Test(groups = "Functional")
+ public void testParseMatrix_aaindexFormat() throws MalformedURLException,
+ IOException
+ {
+ /*
+ * aaindex format has scores for diagonal and below only
+ */
+ String data = "H MyTest\n" + "D My description\n" + "R PMID:1438297\n"
+ + "A Authors, names\n" + "T Journal title\n"
+ + "J Journal reference\n" + "* matrix in 1/3 Bit Units\n"
+ + "M rows = ABC, cols = ABC\n" + "A\t1.0\n"
+ + "B\t4.0\t5.0\n"
+ + "C\t7.0\t8.0\t9.0\n";
+ FileParse fp = new FileParse(data, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ ScoreMatrix sm = parser.parseMatrix();
+
+ assertNotNull(sm);
+ assertEquals(sm.getSize(), 3);
+ assertEquals(sm.getName(), "MyTest");
+ assertEquals(sm.getDescription(), "My description");
+ assertEquals(sm.getPairwiseScore('A', 'A'), 1.0f);
+ assertEquals(sm.getPairwiseScore('A', 'B'), 4.0f);
+ assertEquals(sm.getPairwiseScore('A', 'C'), 7.0f);
+ assertEquals(sm.getPairwiseScore('B', 'A'), 4.0f);
+ assertEquals(sm.getPairwiseScore('B', 'B'), 5.0f);
+ assertEquals(sm.getPairwiseScore('B', 'C'), 8.0f);
+ assertEquals(sm.getPairwiseScore('C', 'C'), 9.0f);
+ assertEquals(sm.getPairwiseScore('C', 'B'), 8.0f);
+ assertEquals(sm.getPairwiseScore('C', 'A'), 7.0f);
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_aaindex_mMissing()
+ throws MalformedURLException,
+ IOException
+ {
+ /*
+ * aaindex format but M cols=, rows= is missing
+ */
+ String data = "H MyTest\n" + "A\t1.0\n"
+ + "B\t4.0\t5.0\n"
+ + "C\t7.0\t8.0\t9.0\n";
+ FileParse fp = new FileParse(data, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ try
+ {
+ parser.parseMatrix();
+ fail("Expected exception");
+ } catch (FileFormatException e)
+ {
+ assertEquals(e.getMessage(), "No alphabet specified in matrix file");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_aaindex_rowColMismatch()
+ throws MalformedURLException,
+ IOException
+ {
+ String data = "H MyTest\n" + "M rows=ABC, cols=ABD\n" + "A\t1.0\n"
+ + "B\t4.0\t5.0\n"
+ + "C\t7.0\t8.0\t9.0\n";
+ FileParse fp = new FileParse(data, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ try
+ {
+ parser.parseMatrix();
+ fail("Expected exception");
+ } catch (FileFormatException e)
+ {
+ assertEquals(
+ e.getMessage(),
+ "Unexpected aaIndex score matrix data at line 2: M rows=ABC, cols=ABD rows != cols");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_ncbiHeaderRepeated()
+ {
+ String data = "ScoreMatrix BLOSUM\nScoreMatrix PAM250\nX Y\n1 2\n3 4\n";
+ try
+ {
+ new ScoreMatrixFile(new FileParse(data, DataSourceType.PASTE))
+ .parseMatrix();
+ fail("expected exception");
+ } catch (IOException e)
+ {
+ assertEquals(e.getMessage(),
+ "Error: 'ScoreMatrix' repeated in file at line 2");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_aaindex_tooManyRows()
+ throws MalformedURLException,
+ IOException
+ {
+ String data = "H MyTest\n" + "M rows=ABC, cols=ABC\n" + "A\t1.0\n"
+ + "B\t4.0\t5.0\n" + "C\t7.0\t8.0\t9.0\n" + "C\t7.0\t8.0\t9.0\n";
+ FileParse fp = new FileParse(data, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ try
+ {
+ parser.parseMatrix();
+ fail("Expected exception");
+ } catch (FileFormatException e)
+ {
+ assertEquals(e.getMessage(), "Too many data rows in matrix file");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_aaindex_extraDataLines()
+ throws MalformedURLException,
+ IOException
+ {
+ String data = "H MyTest\n" + "M rows=ABC, cols=ABC\n" + "A\t1.0\n"
+ + "B\t4.0\t5.0\n" + "C\t7.0\t8.0\t9.0\n" + "something extra\n";
+ FileParse fp = new FileParse(data, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ try
+ {
+ parser.parseMatrix();
+ fail("Expected exception");
+ } catch (FileFormatException e)
+ {
+ assertEquals(e.getMessage(), "Too many data rows in matrix file");
+ }
+ }
+
+ @Test(groups = "Functional")
+ public void testParseMatrix_aaindex_tooFewColumns()
+ throws MalformedURLException,
+ IOException
+ {
+ String data = "H MyTest\n" + "M rows=ABC, cols=ABC\n" + "A\t1.0\n"
+ + "B\t4.0\t5.0\n" + "C\t7.0\t8.0\n";
+ FileParse fp = new FileParse(data, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+ try
+ {
+ parser.parseMatrix();
+ fail("Expected exception");
+ } catch (FileFormatException e)
+ {
+ assertEquals(
+ e.getMessage(),
+ "Expected 3 scores at line 5: 'C\t7.0\t8.0' but found 2");
+ }
+ }
+
+ /**
+ * Test a successful parse and register of a score matrix file
+ *
+ * @throws IOException
+ * @throws MalformedURLException
+ */
+ @Test(groups = "Functional")
+ public void testParse_ncbiFormat() throws MalformedURLException,
+ IOException
+ {
+ assertNull(ScoreModels.getInstance().getScoreModel("MyNewTest", null));
+
+ String data = "ScoreMatrix MyNewTest\n" + "\tA\tB\tC\n"
+ + "A\t1.0\t2.0\t3.0\n" + "B\t4.0\t5.0\t6.0\n"
+ + "C\t7.0\t8.0\t9.0\n";
+ FileParse fp = new FileParse(data, DataSourceType.PASTE);
+ ScoreMatrixFile parser = new ScoreMatrixFile(fp);
+
+ parser.parse();
+
+ ScoreMatrix sm = (ScoreMatrix) ScoreModels.getInstance().getScoreModel(
+ "MyNewTest", null);
+ assertNotNull(sm);
+ assertEquals(sm.getName(), "MyNewTest");
+ assertEquals(parser.getMatrixName(), "MyNewTest");
+ assertEquals(sm.getPairwiseScore('A', 'A'), 1.0f);
+ assertEquals(sm.getPairwiseScore('B', 'c'), 6.0f);
+ assertEquals(sm.getSize(), 3);
+ }
+}
import jalview.gui.JvOptionPane;
import java.io.File;
+import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@Test(groups = { "Functional" })
public void pfamFileIO() throws Exception
{
- testFileIOwithFormat(new File(PfamFile), FileFormat.Stockholm, -1, 0);
+ testFileIOwithFormat(new File(PfamFile), FileFormat.Stockholm, -1, 0,
+ false, false, false);
}
@Test(groups = { "Functional" })
@Test(groups = { "Functional" })
public void rfamFileIO() throws Exception
{
- testFileIOwithFormat(new File(RfamFile), FileFormat.Stockholm, 2, 1);
+ testFileIOwithFormat(new File(RfamFile), FileFormat.Stockholm, 2, 1,
+ false, false, false);
}
/**
* @param ioformat
* - label for IO class used to write and read back in the data from
* f
+ * @param ignoreFeatures
+ * @param ignoreRowVisibility
+ * @param allowNullAnnotations
*/
public static void testFileIOwithFormat(File f, FileFormatI ioformat,
- int naliannot, int nminseqann)
+ int naliannot, int nminseqann, boolean ignoreFeatures,
+ boolean ignoreRowVisibility, boolean allowNullAnnotations)
{
System.out.println("Reading file: " + f);
String ff = f.getPath();
"Identify routine could not recognise output generated by '"
+ ioformat + "' writer",
ioformat.equals(identifyoutput));
- testAlignmentEquivalence(al, al_input, false);
+ testAlignmentEquivalence(al, al_input, ignoreFeatures,
+ ignoreRowVisibility, allowNullAnnotations);
int numaliannot = 0, numsqswithali = 0;
for (AlignmentAnnotation ala : al_input.getAlignmentAnnotation())
{
public static void testAlignmentEquivalence(AlignmentI al,
AlignmentI al_input, boolean ignoreFeatures)
{
+ testAlignmentEquivalence(al, al_input, ignoreFeatures, false, false);
+ }
+
+ /**
+ * assert alignment equivalence - uses special comparators for RNA structure
+ * annotation rows.
+ *
+ * @param al
+ * 'original'
+ * @param al_input
+ * 'secondary' or generated alignment from some datapreserving
+ * transformation
+ * @param ignoreFeatures
+ * when true, differences in sequence feature annotation are ignored
+ *
+ * @param ignoreRowVisibility
+ * when true, do not fail if there are differences in the visibility
+ * of annotation rows
+ * @param allowNullAnnotation
+ * when true, positions in alignment annotation that are null will be
+ * considered equal to positions containing annotation where
+ * Annotation.isWhitespace() returns true.
+ *
+ */
+ public static void testAlignmentEquivalence(AlignmentI al,
+ AlignmentI al_input, boolean ignoreFeatures,
+ boolean ignoreRowVisibility, boolean allowNullAnnotation)
+ {
assertNotNull("Original alignment was null", al);
assertNotNull("Generated alignment was null", al_input);
{
if (aa_new.length > i)
{
- assertTrue("Different alignment annotation at position " + i,
- equalss(aa_original[i], aa_new[i]));
+ assertEqualSecondaryStructure(
+ "Different alignment annotation at position " + i,
+ aa_original[i], aa_new[i], allowNullAnnotation);
// compare graphGroup or graph properties - needed to verify JAL-1299
assertEquals("Graph type not identical.", aa_original[i].graph,
aa_new[i].graph);
- assertEquals("Visibility not identical.", aa_original[i].visible,
+ if (!ignoreRowVisibility)
+ {
+ assertEquals("Visibility not identical.",
+ aa_original[i].visible,
aa_new[i].visible);
+ }
assertEquals("Threshold line not identical.",
aa_original[i].threshold, aa_new[i].threshold);
// graphGroup may differ, but pattern should be the same
{
annot_original = al.getSequenceAt(i).getAnnotation()[j];
annot_new = al_input.getSequenceAt(in).getAnnotation()[j];
- assertTrue("Different annotation elements",
- equalss(annot_original, annot_new));
+ assertEqualSecondaryStructure(
+ "Different annotation elements", annot_original,
+ annot_new, allowNullAnnotation);
}
}
}
}
}
- /*
- * compare annotations
+ /**
+ * compare two annotation rows, with special support for secondary structure
+ * comparison. With RNA, only the value and the secondaryStructure symbols are
+ * compared, displayCharacter and description are ignored. Annotations where
+ * Annotation.isWhitespace() is true are always considered equal.
+ *
+ * @param message
+ * - not actually used yet..
+ * @param annot_or
+ * - the original annotation
+ * @param annot_new
+ * - the one compared to the original annotation
+ * @param allowNullEquivalence
+ * when true, positions in alignment annotation that are null will be
+ * considered equal to non-null positions for which
+ * Annotation.isWhitespace() is true.
*/
- private static boolean equalss(AlignmentAnnotation annot_or,
- AlignmentAnnotation annot_new)
+ private static void assertEqualSecondaryStructure(String message,
+ AlignmentAnnotation annot_or, AlignmentAnnotation annot_new,
+ boolean allowNullEqivalence)
{
+ // TODO: test to cover this assert behaves correctly for all allowed
+ // variations of secondary structure annotation row equivalence
if (annot_or.annotations.length != annot_new.annotations.length)
{
- System.err.println("Different lengths for annotation row elements: "
+ fail("Different lengths for annotation row elements: "
+ annot_or.annotations.length + "!="
+ annot_new.annotations.length);
- return false;
}
+ boolean isRna = annot_or.isRNA();
+ assertTrue("Expected " + (isRna ? " valid RNA " : " no RNA ")
+ + " secondary structure in the row.",
+ isRna == annot_new.isRNA());
for (int i = 0; i < annot_or.annotations.length; i++)
{
Annotation an_or = annot_or.annotations[i], an_new = annot_new.annotations[i];
if (an_or != null && an_new != null)
{
- if (!an_or.displayCharacter.trim().equals(
- an_new.displayCharacter.trim())
- || !("" + an_or.secondaryStructure).trim().equals(
- ("" + an_new.secondaryStructure).trim())
- || (an_or.description != an_new.description && !((an_or.description == null && an_new.description
- .trim().length() == 0)
- || (an_new.description == null && an_or.description
- .trim().length() == 0) || an_or.description
- .trim().equals(an_new.description.trim()))))
+
+ if (isRna)
{
- System.err.println("Annotation Element Mismatch\nElement " + i
- + " in original: " + annot_or.annotations[i].toString()
- + "\nElement " + i + " in new: "
- + annot_new.annotations[i].toString());
- return false;
+ if (an_or.secondaryStructure != an_new.secondaryStructure
+ || ((Float.isNaN(an_or.value) != Float
+ .isNaN(an_new.value)) || an_or.value != an_new.value))
+ {
+ fail("Different RNA secondary structure at column " + i
+ + " expected: [" + annot_or.annotations[i].toString()
+ + "] but got: [" + annot_new.annotations[i].toString()
+ + "]");
+ }
+ }
+ else
+ {
+ // not RNA secondary structure, so expect all elements to match...
+ if ((an_or.isWhitespace() != an_new.isWhitespace())
+ || !an_or.displayCharacter.trim().equals(
+ an_new.displayCharacter.trim())
+ || !("" + an_or.secondaryStructure).trim().equals(
+ ("" + an_new.secondaryStructure).trim())
+ || (an_or.description != an_new.description && !((an_or.description == null && an_new.description
+ .trim().length() == 0)
+ || (an_new.description == null && an_or.description
+ .trim().length() == 0) || an_or.description
+ .trim().equals(an_new.description.trim())))
+ || !((Float.isNaN(an_or.value) && Float
+ .isNaN(an_new.value)) || an_or.value == an_new.value))
+ {
+ fail("Annotation Element Mismatch\nElement " + i
+ + " in original: " + annot_or.annotations[i].toString()
+ + "\nElement " + i + " in new: "
+ + annot_new.annotations[i].toString());
+ }
}
}
else if (annot_or.annotations[i] == null
}
else
{
- System.err.println("Annotation Element Mismatch\nElement "
- + i
- + " in original: "
- + (annot_or.annotations[i] == null ? "is null"
- : annot_or.annotations[i].toString())
- + "\nElement "
- + i
- + " in new: "
- + (annot_new.annotations[i] == null ? "is null"
- : annot_new.annotations[i].toString()));
- return false;
+ if (allowNullEqivalence)
+ {
+ if (an_or != null && an_or.isWhitespace())
+
+ {
+ continue;
+ }
+ if (an_new != null && an_new.isWhitespace())
+ {
+ continue;
+ }
+ }
+ // need also to test for null in one, non-SS annotation in other...
+ fail("Annotation Element Mismatch\nElement " + i + " in original: "
+ + (an_or == null ? "is null" : an_or.toString())
+ + "\nElement " + i + " in new: "
+ + (an_new == null ? "is null" : an_new.toString()));
+ }
+ }
+ }
+
+ /**
+ * @see assertEqualSecondaryStructure - test if two secondary structure
+ * annotations are not equal
+ * @param message
+ * @param an_orig
+ * @param an_new
+ * @param allowNullEquivalence
+ */
+ public static void assertNotEqualSecondaryStructure(String message,
+ AlignmentAnnotation an_orig, AlignmentAnnotation an_new,
+ boolean allowNullEquivalence)
+ {
+ boolean thrown = false;
+ try
+ {
+ assertEqualSecondaryStructure("", an_orig, an_new,
+ allowNullEquivalence);
+ } catch (AssertionError af)
+ {
+ thrown = true;
+ }
+ if (!thrown)
+ {
+ fail("Expected difference for [" + an_orig + "] and [" + an_new + "]");
+ }
+ }
+ private AlignmentAnnotation makeAnnot(Annotation ae)
+ {
+ return new AlignmentAnnotation("label", "description", new Annotation[]
+ { ae });
+ }
+
+ @Test(groups={"Functional"})
+ public void testAnnotationEquivalence()
+ {
+ AlignmentAnnotation one = makeAnnot(new Annotation("", "", ' ', 1));
+ AlignmentAnnotation anotherOne = makeAnnot(new Annotation("", "", ' ',
+ 1));
+ AlignmentAnnotation sheet = makeAnnot(new Annotation("","",'E',0f));
+ AlignmentAnnotation anotherSheet = makeAnnot(new Annotation("","",'E',0f));
+ AlignmentAnnotation sheetWithLabel = makeAnnot(new Annotation("1", "",
+ 'E', 0f));
+ AlignmentAnnotation anotherSheetWithLabel = makeAnnot(new Annotation(
+ "1", "", 'E', 0f));
+ AlignmentAnnotation rnaNoDC = makeAnnot(new Annotation("","",'<',0f));
+ AlignmentAnnotation anotherRnaNoDC = makeAnnot(new Annotation("","",'<',0f));
+ AlignmentAnnotation rnaWithDC = makeAnnot(new Annotation("B", "", '<',
+ 0f));
+ AlignmentAnnotation anotherRnaWithDC = makeAnnot(new Annotation("B",
+ "", '<', 0f));
+
+ // check self equivalence
+ for (boolean allowNull : new boolean[] { true, false })
+ {
+ assertEqualSecondaryStructure("Should be equal", one, anotherOne,
+ allowNull);
+ assertEqualSecondaryStructure("Should be equal", sheet, anotherSheet,
+ allowNull);
+ assertEqualSecondaryStructure("Should be equal", sheetWithLabel,
+ anotherSheetWithLabel, allowNull);
+ assertEqualSecondaryStructure("Should be equal", rnaNoDC,
+ anotherRnaNoDC, allowNull);
+ assertEqualSecondaryStructure("Should be equal", rnaWithDC,
+ anotherRnaWithDC, allowNull);
+ // display character doesn't matter for RNA structure (for 2.10.2)
+ assertEqualSecondaryStructure("Should be equal", rnaWithDC, rnaNoDC,
+ allowNull);
+ assertEqualSecondaryStructure("Should be equal", rnaNoDC, rnaWithDC,
+ allowNull);
+ }
+
+ // verify others are different
+ List<AlignmentAnnotation> aaSet = Arrays.asList(one, sheet,
+ sheetWithLabel, rnaWithDC);
+ for (int p = 0; p < aaSet.size(); p++)
+ {
+ for (int q = 0; q < aaSet.size(); q++)
+ {
+ if (p != q)
+ {
+ assertNotEqualSecondaryStructure("Should be different",
+ aaSet.get(p), aaSet.get(q), false);
+ }
+ else
+ {
+ assertEqualSecondaryStructure("Should be same", aaSet.get(p),
+ aaSet.get(q), false);
+ assertEqualSecondaryStructure("Should be same", aaSet.get(p),
+ aaSet.get(q), true);
+ assertNotEqualSecondaryStructure(
+ "Should be different to empty anot", aaSet.get(p),
+ makeAnnot(Annotation.EMPTY_ANNOTATION), false);
+ assertNotEqualSecondaryStructure(
+ "Should be different to empty annot",
+ makeAnnot(Annotation.EMPTY_ANNOTATION), aaSet.get(q),
+ true);
+ assertNotEqualSecondaryStructure("Should be different to null",
+ aaSet.get(p), makeAnnot(null), false);
+ assertNotEqualSecondaryStructure("Should be different to null",
+ makeAnnot(null), aaSet.get(q), true);
+ }
}
}
- return true;
+
+ // test null
+
+ }
+
+ String aliFile = ">Dm\nAAACCCUUUUACACACGGGAAAGGG";
+ String annFile = "JALVIEW_ANNOTATION\n# Created: Thu May 04 11:16:52 BST 2017\n\n"
+ + "SEQUENCE_REF\tDm\nNO_GRAPH\tsecondary structure\tsecondary structure\t"
+ + "(|(|(|(|, .|, .|, .|, .|)|)|)|)|\t0.0\nROWPROPERTIES\t"
+ + "secondary structure\tscaletofit=true\tshowalllabs=true\tcentrelabs=false";
+
+ String annFileCurlyWuss = "JALVIEW_ANNOTATION\n# Created: Thu May 04 11:16:52 BST 2017\n\n"
+ + "SEQUENCE_REF\tDm\nNO_GRAPH\tsecondary structure\tsecondary structure\t"
+ + "(|(|(|(||{|{||{|{||)|)|)|)||}|}|}|}|\t0.0\nROWPROPERTIES\t"
+ + "secondary structure\tscaletofit=true\tshowalllabs=true\tcentrelabs=false";
+ String annFileFullWuss = "JALVIEW_ANNOTATION\n# Created: Thu May 04 11:16:52 BST 2017\n\n"
+ + "SEQUENCE_REF\tDm\nNO_GRAPH\tsecondary structure\tsecondary structure\t"
+ + "(|(|(|(||{|{||[|[||)|)|)|)||}|}|]|]|\t0.0\nROWPROPERTIES\t"
+ + "secondary structure\tscaletofit=true\tshowalllabs=true\tcentrelabs=false";
+
+ @Test(groups = { "Functional" })
+ public void secondaryStructureForRNASequence() throws Exception
+ {
+ roundTripSSForRNA(aliFile, annFile);
+ }
+
+ @Test(groups = { "Functional" })
+ public void curlyWUSSsecondaryStructureForRNASequence() throws Exception
+ {
+ roundTripSSForRNA(aliFile, annFileCurlyWuss);
+ }
+
+ @Test(groups = { "Functional" })
+ public void fullWUSSsecondaryStructureForRNASequence() throws Exception
+ {
+ roundTripSSForRNA(aliFile, annFileFullWuss);
+ }
+
+ @Test(groups = { "Functional" })
+ public void detectWussBrackets()
+ {
+ for (char ch : new char[] { '{', '}', '[', ']', '(', ')', '<', '>' })
+ {
+ Assert.assertTrue(StockholmFile.DETECT_BRACKETS.matchAt("" + ch, 0),
+ "Didn't recognise " + ch + " as a WUSS bracket");
+ }
+ for (char ch : new char[] { '@', '!', 'V', 'Q', '*', ' ', '-', '.' })
+ {
+ Assert.assertFalse(StockholmFile.DETECT_BRACKETS.matchAt("" + ch, 0),
+ "Shouldn't recognise " + ch + " as a WUSS bracket");
+ }
+ }
+ private static void roundTripSSForRNA(String aliFile, String annFile)
+ throws Exception
+ {
+ AlignmentI al = new AppletFormatAdapter().readFile(aliFile,
+ DataSourceType.PASTE, jalview.io.FileFormat.Fasta);
+ AnnotationFile aaf = new AnnotationFile();
+ aaf.readAnnotationFile(al, annFile, DataSourceType.PASTE);
+ al.getAlignmentAnnotation()[0].visible = true;
+
+ // TODO: create a better 'save as <format>' pattern
+ StockholmFile sf = new StockholmFile(al);
+
+ String stockholmFile = sf.print(al.getSequencesArray(), true);
+
+ AlignmentI newAl = new AppletFormatAdapter().readFile(stockholmFile,
+ DataSourceType.PASTE, jalview.io.FileFormat.Stockholm);
+ // AlignmentUtils.showOrHideSequenceAnnotations(newAl.getViewport()
+ // .getAlignment(), Arrays.asList("Secondary Structure"), newAl
+ // .getViewport().getAlignment().getSequences(), true, true);
+ testAlignmentEquivalence(al, newAl, true, true, true);
+
}
}
PIR_MODELLER=false
GAP_SYMBOL=-
SHOW_QUALITY=true
+SHOW_OCCUPANCY=true
SHOW_GROUP_CONSERVATION=false
SHOW_JWS2_SERVICES=true
SHOW_NPFEATS_TOOLTIP=true
package jalview.math;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotSame;
+import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
public class MatrixTest
{
- final static double DELTA = 0.0001d;
+ final static double DELTA = 0.000001d;
@Test(groups = "Timing")
public void testPreMultiply_timing()
{
- int rows = 500;
- int cols = 1000;
+ int rows = 50; // increase to stress test timing
+ int cols = 100;
double[][] d1 = new double[rows][cols];
double[][] d2 = new double[cols][rows];
Matrix m1 = new Matrix(d1);
}
Matrix m1 = new Matrix(in);
Matrix m2 = (Matrix) m1.copy();
+ assertNotSame(m1, m2);
assertTrue(matrixEquals(m1, m2));
}
ArrayAsserts.assertArrayEquals(m1.getD(), m2.getD(), 0.00001d);
ArrayAsserts.assertArrayEquals(m1.getE(), m2.getE(), 0.00001d);
}
+
+ @Test(groups = "Functional")
+ public void testFindMinMax()
+ {
+ /*
+ * empty matrix case
+ */
+ Matrix m = new Matrix(new double[][] { {} });
+ assertNull(m.findMinMax());
+
+ /*
+ * normal case
+ */
+ double[][] vals = new double[2][];
+ vals[0] = new double[] {7d, 1d, -2.3d};
+ vals[1] = new double[] {-12d, 94.3d, -102.34d};
+ m = new Matrix(vals);
+ double[] minMax = m.findMinMax();
+ assertEquals(minMax[0], -102.34d);
+ assertEquals(minMax[1], 94.3d);
+ }
+
+ @Test(groups = { "Functional", "Timing" })
+ public void testFindMinMax_timing()
+ {
+ Random r = new Random();
+ int size = 1000; // increase to stress test timing
+ double[][] vals = new double[size][size];
+ double max = -Double.MAX_VALUE;
+ double min = Double.MAX_VALUE;
+ for (int i = 0; i < size; i++)
+ {
+ vals[i] = new double[size];
+ for (int j = 0; j < size; j++)
+ {
+ // use nextLong rather than nextDouble to include negative values
+ double d = r.nextLong();
+ if (d > max)
+ {
+ max = d;
+ }
+ if (d < min)
+ {
+ min = d;
+ }
+ vals[i][j] = d;
+ }
+ }
+ Matrix m = new Matrix(vals);
+ long now = System.currentTimeMillis();
+ double[] minMax = m.findMinMax();
+ System.out.println(String.format("findMinMax for %d x %d took %dms",
+ size, size, (System.currentTimeMillis() - now)));
+ assertEquals(minMax[0], min);
+ assertEquals(minMax[1], max);
+ }
+
+ /**
+ * Test range reversal with maximum value becoming zero
+ */
+ @Test(groups = "Functional")
+ public void testReverseRange_maxToZero()
+ {
+ Matrix m1 = new Matrix(
+ new double[][] { { 2, 3.5, 4 }, { -3.4, 4, 15 } });
+
+ /*
+ * subtract all from max: range -3.4 to 15 becomes 18.4 to 0
+ */
+ m1.reverseRange(true);
+ assertEquals(m1.getValue(0, 0), 13d, DELTA);
+ assertEquals(m1.getValue(0, 1), 11.5d, DELTA);
+ assertEquals(m1.getValue(0, 2), 11d, DELTA);
+ assertEquals(m1.getValue(1, 0), 18.4d, DELTA);
+ assertEquals(m1.getValue(1, 1), 11d, DELTA);
+ assertEquals(m1.getValue(1, 2), 0d, DELTA);
+
+ /*
+ * repeat operation - range is now 0 to 18.4
+ */
+ m1.reverseRange(true);
+ assertEquals(m1.getValue(0, 0), 5.4d, DELTA);
+ assertEquals(m1.getValue(0, 1), 6.9d, DELTA);
+ assertEquals(m1.getValue(0, 2), 7.4d, DELTA);
+ assertEquals(m1.getValue(1, 0), 0d, DELTA);
+ assertEquals(m1.getValue(1, 1), 7.4d, DELTA);
+ assertEquals(m1.getValue(1, 2), 18.4d, DELTA);
+ }
+
+ /**
+ * Test range reversal with minimum and maximum values swapped
+ */
+ @Test(groups = "Functional")
+ public void testReverseRange_swapMinMax()
+ {
+ Matrix m1 = new Matrix(
+ new double[][] { { 2, 3.5, 4 }, { -3.4, 4, 15 } });
+
+ /*
+ * swap all values in min-max range
+ * = subtract from (min + max = 11.6)
+ * range -3.4 to 15 becomes 18.4 to -3.4
+ */
+ m1.reverseRange(false);
+ assertEquals(m1.getValue(0, 0), 9.6d, DELTA);
+ assertEquals(m1.getValue(0, 1), 8.1d, DELTA);
+ assertEquals(m1.getValue(0, 2), 7.6d, DELTA);
+ assertEquals(m1.getValue(1, 0), 15d, DELTA);
+ assertEquals(m1.getValue(1, 1), 7.6d, DELTA);
+ assertEquals(m1.getValue(1, 2), -3.4d, DELTA);
+
+ /*
+ * repeat operation - original values restored
+ */
+ m1.reverseRange(false);
+ assertEquals(m1.getValue(0, 0), 2d, DELTA);
+ assertEquals(m1.getValue(0, 1), 3.5d, DELTA);
+ assertEquals(m1.getValue(0, 2), 4d, DELTA);
+ assertEquals(m1.getValue(1, 0), -3.4d, DELTA);
+ assertEquals(m1.getValue(1, 1), 4d, DELTA);
+ assertEquals(m1.getValue(1, 2), 15d, DELTA);
+ }
+
+ @Test(groups = "Functional")
+ public void testMultiply()
+ {
+ Matrix m = new Matrix(new double[][] { { 2, 3.5, 4 }, { -3.4, 4, 15 } });
+ m.multiply(2d);
+ assertEquals(m.getValue(0, 0), 4d, DELTA);
+ assertEquals(m.getValue(0, 1), 7d, DELTA);
+ assertEquals(m.getValue(0, 2), 8d, DELTA);
+ assertEquals(m.getValue(1, 0), -6.8d, DELTA);
+ assertEquals(m.getValue(1, 1), 8d, DELTA);
+ assertEquals(m.getValue(1, 2), 30d, DELTA);
+ }
+
+ @Test(groups = "Functional")
+ public void testConstructor()
+ {
+ double[][] values = new double[][] { { 1, 2, 3 }, { 4, 5, 6 } };
+ Matrix m = new Matrix(values);
+ assertEquals(m.getValue(0, 0), 1d, DELTA);
+
+ /*
+ * verify the matrix has a copy of the original array
+ */
+ assertNotSame(values[0], m.getRow(0));
+ values[0][0] = -1d;
+ assertEquals(m.getValue(0, 0), 1d, DELTA); // unchanged
+ }
}
+++ /dev/null
-/*
- * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
- * Copyright (C) $$Year-Rel$$ The Jalview Authors
- *
- * This file is part of Jalview.
- *
- * Jalview is free software: you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation, either version 3
- * of the License, or (at your option) any later version.
- *
- * Jalview is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
- * The Jalview Authors are detailed in the 'AUTHORS' file.
- */
-package jalview.schemes;
-
-import jalview.api.analysis.ScoreModelI;
-import jalview.gui.JvOptionPane;
-
-import java.util.Map;
-
-import org.testng.annotations.BeforeClass;
-
-public class ScoreMatrixPrinter
-{
-
- @BeforeClass(alwaysRun = true)
- public void setUpJvOptionPane()
- {
- JvOptionPane.setInteractiveMode(false);
- JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
- }
-
- public void printAllMatrices()
- {
- for (Map.Entry<String, ScoreModelI> sm : ResidueProperties.scoreMatrices
- .entrySet())
- {
- System.out.println("Matrix " + sm.getKey());
- System.out.println(sm.getValue().toString());
- }
- }
-
- public void printHTMLMatrices()
- {
- for (Map.Entry<String, ScoreModelI> _sm : ResidueProperties.scoreMatrices
- .entrySet())
- {
- if (_sm.getValue() instanceof ScoreMatrix)
- {
- ScoreMatrix sm = (ScoreMatrix) _sm.getValue();
- System.out.println("Matrix " + _sm.getKey());
- System.out.println(sm.outputMatrix(true));
- }
- }
- }
-
-}
+++ /dev/null
-package jalview.schemes;
-
-import static org.testng.Assert.assertEquals;
-
-import jalview.math.MatrixI;
-
-import org.testng.annotations.Test;
-
-public class ScoreMatrixTest
-{
- @Test(groups = "Functional")
- public void testSymmetric()
- {
- verifySymmetric(ResidueProperties.getScoreMatrix("BLOSUM62"));
- verifySymmetric(ResidueProperties.getScoreMatrix("PAM250"));
- verifySymmetric(ResidueProperties.getScoreMatrix("DNA"));
- }
-
- private void verifySymmetric(ScoreMatrix sm)
- {
- int[][] m = sm.getMatrix();
- int rows = m.length;
- for (int row = 0; row < rows; row++)
- {
- assertEquals(m[row].length, rows);
- for (int col = 0; col < rows; col++)
- {
- assertEquals(m[row][col], m[col][row], String.format("%s [%s, %s]",
- sm.getName(), ResidueProperties.aa[row],
- ResidueProperties.aa[col]));
- }
- }
-
- /*
- * also check the score matrix is sized for
- * the number of symbols scored, plus gap
- */
- assertEquals(rows, (sm.isDNA() ? ResidueProperties.maxNucleotideIndex
- : ResidueProperties.maxProteinIndex) + 1);
- }
-
- /**
- * A test that just asserts the expected values in the Blosum62 score matrix
- */
- @Test(groups = "Functional")
- public void testBlosum62_values()
- {
- ScoreMatrix sm = ResidueProperties.getScoreMatrix("BLOSUM62");
-
- /*
- * verify expected scores against ARNDCQEGHILKMFPSTWYVBZX
- * scraped from https://www.ncbi.nlm.nih.gov/Class/FieldGuide/BLOSUM62.txt
- */
- verifyValues(sm, 'A', new int[] { 4, -1, -2, -2, 0, -1, -1, 0, -2, -1,
- -1, -1, -1, -2, -1, 1, 0, -3, -2, 0, -2, -1, 0 });
- verifyValues(sm, 'R', new int[] { -1, 5, 0, -2, -3, 1, 0, -2, 0, -3,
- -2, 2, -1, -3, -2, -1, -1, -3, -2, -3, -1, 0, -1 });
- verifyValues(sm, 'N', new int[] { -2, 0, 6, 1, -3, 0, 0, 0, 1, -3, -3,
- 0, -2, -3, -2, 1, 0, -4, -2, -3, 3, 0, -1 });
- verifyValues(sm, 'D', new int[] { -2, -2, 1, 6, -3, 0, 2, -1, -1, -3,
- -4, -1, -3, -3, -1, 0, -1, -4, -3, -3, 4, 1, -1 });
- verifyValues(sm, 'C', new int[] { 0, -3, -3, -3, 9, -3, -4, -3, -3, -1,
- -1, -3, -1, -2, -3, -1, -1, -2, -2, -1, -3, -3, -2 });
- verifyValues(sm, 'Q', new int[] { -1, 1, 0, 0, -3, 5, 2, -2, 0, -3, -2,
- 1, 0, -3, -1, 0, -1, -2, -1, -2, 0, 3, -1 });
- verifyValues(sm, 'E', new int[] { -1, 0, 0, 2, -4, 2, 5, -2, 0, -3, -3,
- 1, -2, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1 });
- verifyValues(sm, 'G', new int[] { 0, -2, 0, -1, -3, -2, -2, 6, -2, -4,
- -4, -2, -3, -3, -2, 0, -2, -2, -3, -3, -1, -2, -1 });
- verifyValues(sm, 'H', new int[] { -2, 0, 1, -1, -3, 0, 0, -2, 8, -3,
- -3, -1, -2, -1, -2, -1, -2, -2, 2, -3, 0, 0, -1 });
- verifyValues(sm, 'I', new int[] { -1, -3, -3, -3, -1, -3, -3, -4, -3,
- 4, 2, -3, 1, 0, -3, -2, -1, -3, -1, 3, -3, -3, -1 });
- verifyValues(sm, 'L', new int[] { -1, -2, -3, -4, -1, -2, -3, -4, -3,
- 2, 4, -2, 2, 0, -3, -2, -1, -2, -1, 1, -4, -3, -1 });
- verifyValues(sm, 'K', new int[] { -1, 2, 0, -1, -3, 1, 1, -2, -1, -3,
- -2, 5, -1, -3, -1, 0, -1, -3, -2, -2, 0, 1, -1 });
- verifyValues(sm, 'M', new int[] { -1, -1, -2, -3, -1, 0, -2, -3, -2, 1,
- 2, -1, 5, 0, -2, -1, -1, -1, -1, 1, -3, -1, -1 });
- verifyValues(sm, 'F', new int[] { -2, -3, -3, -3, -2, -3, -3, -3, -1,
- 0, 0, -3, 0, 6, -4, -2, -2, 1, 3, -1, -3, -3, -1 });
- verifyValues(sm, 'P', new int[] { -1, -2, -2, -1, -3, -1, -1, -2, -2,
- -3, -3, -1, -2, -4, 7, -1, -1, -4, -3, -2, -2, -1, -2 });
- verifyValues(sm, 'S', new int[] { 1, -1, 1, 0, -1, 0, 0, 0, -1, -2, -2,
- 0, -1, -2, -1, 4, 1, -3, -2, -2, 0, 0, 0 });
- verifyValues(sm, 'T', new int[] { 0, -1, 0, -1, -1, -1, -1, -2, -2, -1,
- -1, -1, -1, -2, -1, 1, 5, -2, -2, 0, -1, -1, 0 });
- verifyValues(sm, 'W', new int[] { -3, -3, -4, -4, -2, -2, -3, -2, -2,
- -3, -2, -3, -1, 1, -4, -3, -2, 11, 2, -3, -4, -3, -2 });
- verifyValues(sm, 'Y', new int[] { -2, -2, -2, -3, -2, -1, -2, -3, 2,
- -1, -1, -2, -1, 3, -3, -2, -2, 2, 7, -1, -3, -2, -1 });
- verifyValues(sm, 'V', new int[] { 0, -3, -3, -3, -1, -2, -2, -3, -3, 3,
- 1, -2, 1, -1, -2, -2, 0, -3, -1, 4, -3, -2, -1 });
- verifyValues(sm, 'B', new int[] { -2, -1, 3, 4, -3, 0, 1, -1, 0, -3,
- -4, 0, -3, -3, -2, 0, -1, -4, -3, -3, 4, 1, -1 });
- verifyValues(sm, 'Z', new int[] { -1, 0, 0, 1, -3, 3, 4, -2, 0, -3, -3,
- 1, -1, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1 });
- verifyValues(sm, 'X', new int[] { 0, -1, -1, -1, -2, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -2, 0, 0, -2, -1, -1, -1, -1, -1 });
- }
- /**
- * Helper method to check pairwise scores for one residue
- *
- * @param sm
- * @param res
- * @param expected
- * score values against 'res', in ResidueProperties.aaIndex order
- */
- private void verifyValues(ScoreMatrix sm, char res, int[] expected)
- {
- for (int j = 0; j < expected.length; j++)
- {
- char c2 = ResidueProperties.aa[j].charAt(0);
- assertEquals(sm.getPairwiseScore(res, c2), expected[j],
- String.format("%s->%s", res, c2));
- }
- }
-
- @Test(groups = "Functional")
- public void testComputePairwiseScores()
- {
- String[] seqs = new String[] { "FKL", "R-D", "QIA", "GWC" };
- ScoreMatrix sm = ResidueProperties.getScoreMatrix("BLOSUM62");
-
- MatrixI pairwise = sm.computePairwiseScores(seqs);
-
- /*
- * should be NxN where N = number of sequences
- */
- assertEquals(pairwise.height(), 4);
- assertEquals(pairwise.width(), 4);
-
- /*
- * should be symmetrical (because BLOSUM62 is)
- */
- for (int i = 0; i < pairwise.height(); i++)
- {
- for (int j = 0; j < pairwise.width(); j++)
- {
- assertEquals(pairwise.getValue(i, j), pairwise.getValue(j, i),
- "Not symmetric");
- }
- }
- /*
- * verify expected BLOSUM dot product scores
- */
- // F.F + K.K + L.L = 6 + 5 + 4 = 15
- assertEquals(pairwise.getValue(0, 0), 15d);
- // R.R + -.- + D.D = 5 + 1 + 6 = 12
- assertEquals(pairwise.getValue(1, 1), 12d);
- // Q.Q + I.I + A.A = 5 + 4 + 4 = 13
- assertEquals(pairwise.getValue(2, 2), 13d);
- // G.G + W.W + C.C = 6 + 11 + 9 = 26
- assertEquals(pairwise.getValue(3, 3), 26d);
- // F.R + K.- + L.D = -3 + -4 + -4 = -11
- assertEquals(pairwise.getValue(0, 1), -11d);
- // F.Q + K.I + L.A = -3 + -3 + -1 = -7
- assertEquals(pairwise.getValue(0, 2), -7d);
- // F.G + K.W + L.C = -3 + -3 + -1 = -7
- assertEquals(pairwise.getValue(0, 3), -7d);
- // R.Q + -.I + D.A = 1 + -4 + -2 = -5
- assertEquals(pairwise.getValue(1, 2), -5d);
- // R.G + -.W + D.C = -2 + -4 + -3 = -9
- assertEquals(pairwise.getValue(1, 3), -9d);
- // Q.G + I.W + A.C = -2 + -3 + 0 = -5
- assertEquals(pairwise.getValue(2, 3), -5d);
- }
-}
import jalview.api.SequenceRenderer;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.PDBEntry;
import jalview.datamodel.PDBEntry.Type;
import jalview.datamodel.Sequence;
@Override
public String superposeStructures(AlignmentI[] als, int[] alm,
- ColumnSelection[] alc)
+ HiddenColumns[] alc)
{
return null;
}
@Test(groups = { "Functional" })
public void testPID_includingGaps()
{
- String seq1 = "ABCDEF";
+ String seq1 = "ABCDEFG"; // extra length here is ignored
String seq2 = "abcdef";
assertEquals("identical", 100f, Comparison.PID(seq1, seq2), 0.001f);
int length = seq1.length();
// match gap-residue, match gap-gap: 9/10 identical
+ // TODO should gap-gap be included in a PID score? JAL-791
assertEquals(90f, Comparison.PID(seq1, seq2, 0, length, true, false),
0.001f);
// overloaded version of the method signature above:
assertEquals(90f, Comparison.PID(seq1, seq2), 0.001f);
// don't match gap-residue, match gap-gap: 7/10 identical
+ // TODO should gap-gap be included in a PID score?
assertEquals(70f, Comparison.PID(seq1, seq2, 0, length, false, false),
0.001f);
}
public void testPID_ungappedOnly()
{
// 5 identical, 2 gap-gap, 2 gap-residue, 1 mismatch
- String seq1 = "a--b-cdefh";
+ // the extra length of seq1 is ignored
+ String seq1 = "a--b-cdefhr";
String seq2 = "a---bcdefg";
int length = seq1.length();
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResultsI;
import jalview.datamodel.Sequence;
setupMappedAlignments();
ColumnSelection colsel = new ColumnSelection();
+ HiddenColumns hidden = new HiddenColumns();
/*
* Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
* in dna respectively, overall 0-4
*/
colsel.addElement(0);
- ColumnSelection cs = MappingUtils.mapColumnSelection(colsel,
- proteinView, dnaView);
+ ColumnSelection cs = new ColumnSelection();
+ HiddenColumns hs = new HiddenColumns();
+ MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
+ cs, hs);
assertEquals("[0, 1, 2, 3, 4]", cs.getSelected().toString());
/*
* Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
*/
+ cs.clear();
colsel.clear();
colsel.addElement(1);
- cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
+ MappingUtils.mapColumnSelection(colsel, hidden, proteinView, dnaView,
+ cs, hs);
assertEquals("[0, 1, 2, 3]", cs.getSelected().toString());
/*
* Column 2 in protein picks up gaps only - no mapping
*/
+ cs.clear();
colsel.clear();
colsel.addElement(2);
- cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
+ MappingUtils.mapColumnSelection(colsel, hidden, proteinView,
+ dnaView, cs, hs);
assertEquals("[]", cs.getSelected().toString());
/*
* Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
* 6-9, 6-10, 5-8 respectively, overall to 5-10
*/
+ cs.clear();
colsel.clear();
colsel.addElement(3);
- cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
+ MappingUtils.mapColumnSelection(colsel, hidden, proteinView,
+ dnaView, cs, hs);
assertEquals("[5, 6, 7, 8, 9, 10]", cs.getSelected().toString());
/*
* Combine selection of columns 1 and 3 to get a discontiguous mapped
* selection
*/
+ cs.clear();
colsel.clear();
colsel.addElement(1);
colsel.addElement(3);
- cs = MappingUtils.mapColumnSelection(colsel, proteinView, dnaView);
+ MappingUtils.mapColumnSelection(colsel, hidden, proteinView,
+ dnaView, cs, hs);
assertEquals("[0, 1, 2, 3, 5, 6, 7, 8, 9, 10]", cs.getSelected()
.toString());
}
setupMappedAlignments();
ColumnSelection colsel = new ColumnSelection();
+ HiddenColumns hidden = new HiddenColumns();
/*
* Column 0 in dna picks up first bases which map to residue 1, columns 0-1
* in protein.
*/
+ ColumnSelection cs = new ColumnSelection();
+ HiddenColumns hs = new HiddenColumns();
colsel.addElement(0);
- ColumnSelection cs = MappingUtils.mapColumnSelection(colsel, dnaView,
- proteinView);
+ MappingUtils.mapColumnSelection(colsel, hidden, dnaView, proteinView,
+ cs, hs);
assertEquals("[0, 1]", cs.getSelected().toString());
/*
colsel.addElement(3);
colsel.addElement(4);
colsel.addElement(5);
- cs = MappingUtils.mapColumnSelection(colsel, dnaView, proteinView);
+ cs.clear();
+ MappingUtils.mapColumnSelection(colsel, hidden, dnaView, proteinView,
+ cs, hs);
assertEquals("[0, 1, 3]", cs.getSelected().toString());
}
public void testMapColumnSelection_null() throws IOException
{
setupMappedAlignments();
- ColumnSelection cs = MappingUtils.mapColumnSelection(null, dnaView,
- proteinView);
+ ColumnSelection cs = new ColumnSelection();
+ HiddenColumns hs = new HiddenColumns();
+ MappingUtils.mapColumnSelection(null, null, dnaView, proteinView, cs,
+ hs);
assertTrue("mapped selection not empty", cs.getSelected().isEmpty());
}
setupMappedAlignments();
ColumnSelection proteinSelection = new ColumnSelection();
+ HiddenColumns hiddenCols = new HiddenColumns();
/*
* Column 0 in protein picks up Seq2/L, Seq3/G which map to cols 0-4 and 0-3
* in dna respectively, overall 0-4
*/
- proteinSelection.hideColumns(0);
- ColumnSelection dnaSelection = MappingUtils.mapColumnSelection(
- proteinSelection, proteinView, dnaView);
+ proteinSelection.hideSelectedColumns(0, hiddenCols);
+ ColumnSelection dnaSelection = new ColumnSelection();
+ HiddenColumns dnaHidden = new HiddenColumns();
+ MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
+ proteinView, dnaView, dnaSelection, dnaHidden);
assertEquals("[]", dnaSelection.getSelected().toString());
- List<int[]> hidden = dnaSelection.getHiddenColumns();
+ List<int[]> hidden = dnaHidden.getHiddenRegions();
assertEquals(1, hidden.size());
assertEquals("[0, 4]", Arrays.toString(hidden.get(0)));
/*
* Column 1 in protein picks up Seq1/K which maps to cols 0-3 in dna
*/
- proteinSelection.revealAllHiddenColumns();
+ dnaSelection = new ColumnSelection();
+ dnaHidden = new HiddenColumns();
+ hiddenCols.revealAllHiddenColumns(proteinSelection);
// the unhidden columns are now marked selected!
assertEquals("[0]", proteinSelection.getSelected().toString());
// deselect these or hideColumns will be expanded to include 0
proteinSelection.clear();
- proteinSelection.hideColumns(1);
- dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
- proteinView, dnaView);
- hidden = dnaSelection.getHiddenColumns();
+ proteinSelection.hideSelectedColumns(1, hiddenCols);
+ MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
+ proteinView, dnaView, dnaSelection, dnaHidden);
+ hidden = dnaHidden.getHiddenRegions();
assertEquals(1, hidden.size());
assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
/*
* Column 2 in protein picks up gaps only - no mapping
*/
- proteinSelection.revealAllHiddenColumns();
+ dnaSelection = new ColumnSelection();
+ dnaHidden = new HiddenColumns();
+ hiddenCols.revealAllHiddenColumns(proteinSelection);
proteinSelection.clear();
- proteinSelection.hideColumns(2);
- dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
- proteinView, dnaView);
- assertTrue(dnaSelection.getHiddenColumns().isEmpty());
+ proteinSelection.hideSelectedColumns(2, hiddenCols);
+ MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
+ proteinView, dnaView, dnaSelection, dnaHidden);
+ assertTrue(dnaHidden.getHiddenRegions().isEmpty());
/*
* Column 3 in protein picks up Seq1/P, Seq2/Q, Seq3/S which map to columns
* 6-9, 6-10, 5-8 respectively, overall to 5-10
*/
- proteinSelection.revealAllHiddenColumns();
+ dnaSelection = new ColumnSelection();
+ dnaHidden = new HiddenColumns();
+ hiddenCols.revealAllHiddenColumns(proteinSelection);
proteinSelection.clear();
- proteinSelection.hideColumns(3); // 5-10 hidden in dna
+ proteinSelection.hideSelectedColumns(3, hiddenCols); // 5-10 hidden in dna
proteinSelection.addElement(1); // 0-3 selected in dna
- dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
- proteinView, dnaView);
+ MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
+ proteinView, dnaView, dnaSelection, dnaHidden);
assertEquals("[0, 1, 2, 3]", dnaSelection.getSelected().toString());
- hidden = dnaSelection.getHiddenColumns();
+ hidden = dnaHidden.getHiddenRegions();
assertEquals(1, hidden.size());
assertEquals("[5, 10]", Arrays.toString(hidden.get(0)));
/*
* Combine hiding columns 1 and 3 to get discontiguous hidden columns
*/
- proteinSelection.revealAllHiddenColumns();
+ dnaSelection = new ColumnSelection();
+ dnaHidden = new HiddenColumns();
+ hiddenCols.revealAllHiddenColumns(proteinSelection);
proteinSelection.clear();
- proteinSelection.hideColumns(1);
- proteinSelection.hideColumns(3);
- dnaSelection = MappingUtils.mapColumnSelection(proteinSelection,
- proteinView, dnaView);
- hidden = dnaSelection.getHiddenColumns();
+ proteinSelection.hideSelectedColumns(1, hiddenCols);
+ proteinSelection.hideSelectedColumns(3, hiddenCols);
+ MappingUtils.mapColumnSelection(proteinSelection, hiddenCols,
+ proteinView, dnaView, dnaSelection, dnaHidden);
+ hidden = dnaHidden.getHiddenRegions();
assertEquals(2, hidden.size());
assertEquals("[0, 3]", Arrays.toString(hidden.get(0)));
assertEquals("[5, 10]", Arrays.toString(hidden.get(1)));
--- /dev/null
+package jalview.util;
+
+import static org.testng.Assert.assertEquals;
+
+import java.awt.Color;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+public class SetUtilsTest
+{
+ @Test(groups = "Functional")
+ public void testCountDisjunction()
+ {
+ Set<Color> s1 = new HashSet<Color>();
+ assertEquals(SetUtils.countDisjunction(null, null), 0);
+ assertEquals(SetUtils.countDisjunction(s1, null), 0);
+ assertEquals(SetUtils.countDisjunction(null, s1), 0);
+ s1.add(Color.white);
+ assertEquals(SetUtils.countDisjunction(s1, null), 1);
+ assertEquals(SetUtils.countDisjunction(null, s1), 1);
+ assertEquals(SetUtils.countDisjunction(s1, null), 1);
+ assertEquals(SetUtils.countDisjunction(s1, s1), 0);
+
+ Set<Object> s2 = new HashSet<Object>();
+ assertEquals(SetUtils.countDisjunction(s2, s2), 0);
+ assertEquals(SetUtils.countDisjunction(s1, s2), 1);
+ assertEquals(SetUtils.countDisjunction(s2, s1), 1);
+
+ s1.add(Color.yellow);
+ s1.add(Color.blue);
+ s2.add(new Color(Color.yellow.getRGB()));
+
+ /*
+ * now s1 is {white, yellow, blue}
+ * s2 is {yellow'}
+ */
+ assertEquals(SetUtils.countDisjunction(s1, s2), 2);
+ s2.add(Color.blue);
+ assertEquals(SetUtils.countDisjunction(s1, s2), 1);
+ s2.add(Color.pink);
+ assertEquals(SetUtils.countDisjunction(s1, s2), 2);
+
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.viewmodel;
+
+import static org.testng.Assert.assertEquals;
+
+import jalview.analysis.AlignmentGenerator;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceCollectionI;
+import jalview.datamodel.SequenceGroup;
+import jalview.datamodel.SequenceI;
+
+import java.util.Hashtable;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+@Test(singleThreaded = true)
+public class OverviewDimensionsHideHiddenTest
+{
+ AlignmentI al;
+
+ OverviewDimensionsHideHidden od;
+
+ // cached widths and heights
+ int boxWidth;
+ int boxHeight;
+ int viewHeight;
+ int viewWidth;
+ int alheight;
+ int alwidth;
+
+ ViewportRanges vpranges;
+
+ Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
+
+ HiddenColumns hiddenCols = new HiddenColumns();
+
+ @BeforeClass(alwaysRun = true)
+ public void setUpAlignment()
+ {
+ // create random alignment
+ AlignmentGenerator gen = new AlignmentGenerator(false);
+ al = gen.generate(157, 525, 123, 5, 5);
+ }
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp()
+ {
+ if (!hiddenRepSequences.isEmpty())
+ {
+ al.getHiddenSequences().showAll(hiddenRepSequences);
+ }
+ ColumnSelection colsel = new ColumnSelection();
+ hiddenCols.revealAllHiddenColumns(colsel);
+
+ vpranges = new ViewportRanges(al);
+ vpranges.setStartRes(0);
+ vpranges.setEndRes(62);
+ vpranges.setStartSeq(0);
+ vpranges.setEndSeq(17);
+
+ viewHeight = vpranges.getEndSeq() - vpranges.getStartSeq() + 1;
+ viewWidth = vpranges.getEndRes() - vpranges.getStartRes() + 1;
+
+ HiddenColumns hiddenCols = new HiddenColumns();
+
+ od = new OverviewDimensionsHideHidden(vpranges, true);
+ // Initial box sizing - default path through code
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+
+ mouseClick(od, 0, 0);
+ moveViewport(0, 0);
+
+ // calculate with visible values
+ alheight = vpranges.getVisibleAlignmentHeight();
+ alwidth = vpranges.getVisibleAlignmentWidth();
+
+ boxWidth = Math.round((float) (vpranges.getEndRes()
+ - vpranges.getStartRes() + 1)
+ * od.getWidth() / alwidth);
+ boxHeight = Math.round((float) (vpranges.getEndSeq()
+ - vpranges.getStartSeq() + 1)
+ * od.getSequencesHeight() / alheight);
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void cleanUp()
+ {
+ al = null;
+ }
+
+ /**
+ * Test that the OverviewDimensions constructor sets width and height
+ * correctly
+ */
+ @Test(groups = { "Functional" })
+ public void testConstructor()
+ {
+ SequenceI seqa = new Sequence("Seq1", "ABC");
+ SequenceI seqb = new Sequence("Seq2", "ABC");
+ SequenceI seqc = new Sequence("Seq3", "ABC");
+ SequenceI seqd = new Sequence("Seq4", "ABC");
+ SequenceI seqe = new Sequence("Seq5",
+ "ABCABCABCABCABCABCABCABCBACBACBACBAC");
+
+ int defaultGraphHeight = 20;
+ int maxWidth = 400;
+ int minWidth = 120;
+ int maxSeqHeight = 300;
+ int minSeqHeight = 40;
+
+ // test for alignment with width > height
+ SequenceI[] seqs1 = new SequenceI[] { seqa, seqb };
+ Alignment al1 = new Alignment(seqs1);
+ ViewportRanges props = new ViewportRanges(al1);
+
+ OverviewDimensions od = new OverviewDimensionsHideHidden(props, true);
+ int scaledHeight = 267;
+ assertEquals(od.getGraphHeight(), defaultGraphHeight);
+ assertEquals(od.getSequencesHeight(), scaledHeight);
+ assertEquals(od.getWidth(), maxWidth);
+ assertEquals(od.getHeight(), scaledHeight + defaultGraphHeight);
+
+ // test for alignment with width < height
+ SequenceI[] seqs2 = new SequenceI[] { seqa, seqb, seqc, seqd };
+ Alignment al2 = new Alignment(seqs2);
+ props = new ViewportRanges(al2);
+
+ od = new OverviewDimensionsHideHidden(props, true);
+ int scaledWidth = 300;
+ assertEquals(od.getGraphHeight(), defaultGraphHeight);
+ assertEquals(od.getSequencesHeight(), maxSeqHeight);
+ assertEquals(od.getWidth(), scaledWidth);
+ assertEquals(od.getHeight(), scaledWidth + defaultGraphHeight);
+
+ // test for alignment with width > height and sequence height scaled below
+ // min value
+ SequenceI[] seqs3 = new SequenceI[] { seqe };
+ Alignment al3 = new Alignment(seqs3);
+ props = new ViewportRanges(al3);
+
+ od = new OverviewDimensionsHideHidden(props, true);
+ assertEquals(od.getGraphHeight(), defaultGraphHeight);
+ assertEquals(od.getSequencesHeight(), minSeqHeight);
+ assertEquals(od.getWidth(), maxWidth);
+ assertEquals(od.getHeight(), minSeqHeight + defaultGraphHeight);
+
+ // test for alignment with width < height and width scaled below min value
+ SequenceI[] seqs4 = new SequenceI[] { seqa, seqb, seqc, seqd, seqa,
+ seqb, seqc, seqd, seqa, seqb, seqc, seqd, seqa, seqb, seqc, seqd };
+ Alignment al4 = new Alignment(seqs4);
+ props = new ViewportRanges(al4);
+
+ od = new OverviewDimensionsHideHidden(props, true);
+ assertEquals(od.getGraphHeight(), defaultGraphHeight);
+ assertEquals(od.getSequencesHeight(), maxSeqHeight);
+ assertEquals(od.getWidth(), minWidth);
+ assertEquals(od.getHeight(), maxSeqHeight + defaultGraphHeight);
+
+ Alignment al5 = new Alignment(seqs4);
+ props = new ViewportRanges(al5);
+
+ od = new OverviewDimensionsHideHidden(props, false);
+ assertEquals(od.getGraphHeight(), 0);
+ assertEquals(od.getSequencesHeight(), maxSeqHeight);
+ assertEquals(od.getWidth(), minWidth);
+ assertEquals(od.getHeight(), maxSeqHeight);
+ }
+
+ /**
+ * Test that validation after mouse adjustments to boxX and boxY sets box
+ * dimensions and scroll values correctly, when there are no hidden rows or
+ * columns.
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromMouseClick()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // negative boxX value reset to 0
+ mouseClick(od, -5, 10);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollRow(),
+ Math.round((float) 10 * alheight / od.getSequencesHeight()));
+ assertEquals(od.getScrollCol(), 0);
+
+ // negative boxY value reset to 0
+ mouseClick(od, 6, -2);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) 6 * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // overly large boxX value reset to width-boxWidth
+ mouseClick(od, 100, 6);
+ assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
+ assertEquals(od.getBoxY(), 6);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()));
+
+ // overly large boxY value reset to sequenceHeight - boxHeight
+ mouseClick(od, 10, 520);
+ assertEquals(od.getBoxX(), 10);
+ assertEquals(od.getBoxY(), od.getSequencesHeight() - od.getBoxHeight());
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+
+ // here (float) od.getBoxY() * alheight / od.getSequencesHeight() = 507.5
+ // and round rounds to 508; however we get 507 working with row values
+ // hence the subtraction of 1
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()) - 1);
+
+ // click past end of alignment, as above
+ mouseClick(od, 3000, 5);
+ assertEquals(od.getBoxX(), od.getWidth() - od.getBoxWidth());
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()));
+
+ // move viewport so startRes non-zero and then mouseclick
+ moveViewportH(50);
+
+ // click at viewport position
+ int oldboxx = od.getBoxX();
+ int oldboxy = od.getBoxY();
+ mouseClick(od, od.getBoxX() + 5, od.getBoxY() + 2);
+ assertEquals(od.getBoxX(), oldboxx + 5);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getBoxY(), oldboxy + 2);
+ assertEquals(od.getScrollRow(),
+ Math.round((float) od.getBoxY() * alheight
+ / od.getSequencesHeight()));
+
+ // click at top corner
+ mouseClick(od, 0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getScrollRow(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden cols at the start
+ * of the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenColsAtStart()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide cols at start and check updated box position is correct
+ int lastHiddenCol = 30;
+ hiddenCols.hideColumns(0, lastHiddenCol);
+
+ testBoxIsAtClickPoint(0, 0);
+
+ // click to right of hidden columns, box moves to click point
+ testBoxIsAtClickPoint(40, 0);
+ assertEquals(od.getScrollRow(), 0);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) 40 * alwidth / od.getWidth()));
+
+ // click to right of hidden columns such that box runs over right hand side
+ // of alignment
+ // box position is adjusted away from the edge
+ // overly large boxX value reset to width-boxWidth
+ int xpos = 100;
+ mouseClick(od, xpos, 0);
+ assertEquals(od.getBoxX(), Math.round(od.getWidth()) - boxWidth);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden cols in the middle
+ * of the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenColsInMiddle()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
+ testBoxIsAtClickPoint(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide columns 63-73, no change to box position or dimensions
+ int firstHidden = 63;
+ int lastHidden = 73;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+ testBoxIsAtClickPoint(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // move box so that it overlaps with hidden cols on one side
+ // box width, boxX and scrollCol as for unhidden case
+ int xpos = 55 - boxWidth; // 55 is position in overview approx halfway
+ // between cols 60 and 70
+ mouseClick(od, xpos, 0);
+ testBoxIsAtClickPoint(xpos, 0);
+ assertEquals(od.getScrollCol(),
+ Math.round(xpos * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // move box so that it completely covers hidden cols
+ // box width, boxX and scrollCol as for unhidden case
+ xpos = 33;
+ mouseClick(od, xpos, 0);
+ testBoxIsAtClickPoint(xpos, 0);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) xpos * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // move box so boxX is in hidden cols, box overhangs at right
+ // boxX and scrollCol at left of hidden area, box width unchanged
+ xpos = 50;
+ mouseClick(od, xpos, 0);
+ testBoxIsAtClickPoint(xpos, 0);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) xpos * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // move box so boxX is to right of hidden cols, but does not go beyond full
+ // width of alignment
+ // box width, boxX and scrollCol all as for non-hidden case
+ xpos = 75;
+ testBoxIsAtClickPoint(xpos, 0);
+ assertEquals(od.getScrollRow(), 0);
+ assertEquals(od.getScrollCol(),
+ Math.round(xpos * alwidth / od.getWidth()));
+
+ // move box so it goes beyond full width of alignment
+ // boxX, scrollCol adjusted back, box width normal
+ xpos = 3000;
+ mouseClick(od, xpos, 0);
+ assertEquals(od.getBoxX(), Math.round(od.getWidth()) - boxWidth);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden cols at the end of
+ * the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenColsAtEnd()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide columns 140-164, no change to box position or dimensions
+ int firstHidden = 140;
+ int lastHidden = 164;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // click to left of hidden cols, without overlapping
+ // boxX, scrollCol and width as normal
+ int xpos = 5;
+ testBoxIsAtClickPoint(xpos, 0);
+ assertEquals(od.getScrollRow(), 0);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) xpos * alwidth / od.getWidth()));
+
+ // click to left of hidden cols, with overlap
+ // boxX and scrollCol adjusted for hidden cols, width normal
+ xpos = Math.round((float) 145 * od.getWidth() / alwidth) - boxWidth;
+ mouseClick(od, xpos, 0);
+ testBoxIsAtClickPoint(xpos, 0);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) xpos * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+
+ // click off end of alignment
+ // boxX and scrollCol adjusted backwards, width normal
+ xpos = 3000;
+ mouseClick(od, xpos, 0);
+ assertEquals(od.getBoxX(), Math.round(od.getWidth()) - boxWidth);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(),
+ Math.round((float) od.getBoxX() * alwidth / od.getWidth()));
+ assertEquals(od.getScrollRow(), 0);
+ }
+
+ /**
+ * Test that the box position is set correctly when set from the viewport,
+ * with no hidden rows or columns
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewport()
+ {
+ // move viewport to start of alignment
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to right
+ moveViewportH(70);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 70 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport down
+ moveViewportV(100);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 70 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(),
+ Math.round(100 * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to bottom right
+ moveViewport(98, 508);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 98 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(),
+ Math.round((float) 508 * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden columns
+ * at the start
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenColsAtStart()
+ {
+ int firstHidden = 0;
+ int lastHidden = 20;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+
+ // move viewport to start of alignment
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to end of alignment - need to make startRes by removing
+ // hidden cols because of how viewport/overview are implemented
+ moveViewport(98 - lastHidden - 1, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) (98 - lastHidden - 1) * od.getWidth()
+ / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden columns
+ * in the middle
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenColsInMiddle()
+ {
+ int firstHidden = 68;
+ int lastHidden = 78;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+
+ // move viewport before hidden columns
+ moveViewport(3, 0);
+
+ assertEquals(od.getBoxX(),
+ Math.round((float) 3 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to left of hidden columns with overlap
+ moveViewport(10, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 10 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to straddle hidden columns
+ moveViewport(63, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 63 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to right of hidden columns, no overlap
+ moveViewport(80 - (lastHidden - firstHidden + 1), 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) (80 - (lastHidden - firstHidden + 1))
+ * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden columns
+ * at the end
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenColsAtEnd()
+ {
+ int firstHidden = 152;
+ int lastHidden = 164;
+ hiddenCols.hideColumns(firstHidden, lastHidden);
+
+ // move viewport before hidden columns
+ moveViewport(3, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) 3 * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to hidden columns
+ // viewport can't actually extend into hidden cols,
+ // so move to the far right edge of the viewport
+ moveViewport(firstHidden - viewWidth, 0);
+ assertEquals(od.getBoxX(),
+ Math.round((float) (firstHidden - viewWidth)
+ * od.getWidth() / alwidth));
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden rows at
+ * the start
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenRowsAtStart()
+ {
+ int firstHidden = 0;
+ int lastHidden = 20;
+ hideSequences(firstHidden, lastHidden);
+
+ // calculate with visible values
+ alheight = vpranges.getVisibleAlignmentHeight();
+ alwidth = vpranges.getVisibleAlignmentWidth();
+
+ boxWidth = Math.round((float) (vpranges.getEndRes()
+ - vpranges.getStartRes() + 1)
+ * od.getWidth() / alwidth);
+ boxHeight = Math.round((float) (vpranges.getEndSeq()
+ - vpranges.getStartSeq() + 1)
+ * od.getSequencesHeight() / alheight);
+
+ // move viewport to start of alignment:
+ // box moves to below hidden rows, height remains same
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to end of alignment
+ moveViewport(0, 525 - viewHeight - lastHidden - 1);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(
+ od.getBoxY(),
+ Math.round((float) (525 - viewHeight - lastHidden - 1)
+ * od.getSequencesHeight()
+ / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden rows in
+ * the middle
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenRowsInMiddle()
+ {
+ int firstHidden = 200;
+ int lastHidden = 210;
+ hideSequences(firstHidden, lastHidden);
+
+ // calculate with visible values
+ alheight = vpranges.getVisibleAlignmentHeight();
+ alwidth = vpranges.getVisibleAlignmentWidth();
+
+ boxWidth = Math.round((float) (vpranges.getEndRes()
+ - vpranges.getStartRes() + 1)
+ * od.getWidth() / alwidth);
+ boxHeight = Math.round((float) (vpranges.getEndSeq()
+ - vpranges.getStartSeq() + 1)
+ * od.getSequencesHeight() / alheight);
+
+ // move viewport to start of alignment:
+ // box, height etc as in non-hidden case
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to straddle hidden rows
+ moveViewport(0, 198);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), Math.round ((float)198 * od.getSequencesHeight()
+ / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test that the box position is set correctly when there are hidden rows at
+ * the bottom
+ */
+ @Test(groups = { "Functional" })
+ public void testSetBoxFromViewportHiddenRowsAtEnd()
+ {
+ int firstHidden = 500;
+ int lastHidden = 524;
+ hideSequences(firstHidden, lastHidden);
+
+ // calculate with visible values
+ alheight = vpranges.getVisibleAlignmentHeight();
+ alwidth = vpranges.getVisibleAlignmentWidth();
+
+ boxWidth = Math.round((float) (vpranges.getEndRes()
+ - vpranges.getStartRes() + 1)
+ * od.getWidth() / alwidth);
+ boxHeight = Math.round((float) (vpranges.getEndSeq()
+ - vpranges.getStartSeq() + 1)
+ * od.getSequencesHeight() / alheight);
+
+ // move viewport to start of alignment:
+ // box, height etc as in non-hidden case
+ moveViewport(0, 0);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // move viewport to end of alignment
+ // viewport sits above hidden rows and does not include them
+ moveViewport(0, firstHidden - viewHeight - 1);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(
+ od.getBoxY(),
+ Math.round((float) (firstHidden - viewHeight - 1)
+ * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden rows at the start
+ * of the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenRowsAtStart()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide rows at start and check updated box position is correct
+ int lastHiddenRow = 30;
+ hideSequences(0, lastHiddenRow);
+
+ // calculate with visible values
+ alheight = vpranges.getVisibleAlignmentHeight();
+ alwidth = vpranges.getVisibleAlignmentWidth();
+
+ boxWidth = Math.round((float) (vpranges.getEndRes()
+ - vpranges.getStartRes() + 1)
+ * od.getWidth() / alwidth);
+ boxHeight = Math.round((float) (vpranges.getEndSeq()
+ - vpranges.getStartSeq() + 1)
+ * od.getSequencesHeight() / alheight);
+
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click below hidden rows
+ mouseClick(od, 0, 150);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 150);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden rows at the middle
+ * of the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenRowsInMiddle()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
+
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide rows in middle and check updated box position is correct
+ // no changes
+ int firstHiddenRow = 50;
+ int lastHiddenRow = 54;
+ hideSequences(firstHiddenRow, lastHiddenRow);
+
+ // calculate with visible values
+ alheight = vpranges.getVisibleAlignmentHeight();
+ alwidth = vpranges.getVisibleAlignmentWidth();
+
+ boxWidth = Math.round((float) (vpranges.getEndRes()
+ - vpranges.getStartRes() + 1)
+ * od.getWidth() / alwidth);
+ boxHeight = Math.round((float) (vpranges.getEndSeq()
+ - vpranges.getStartSeq() + 1)
+ * od.getSequencesHeight() / alheight);
+
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click above hidden rows, so that box overlaps
+ int ypos = 35; // column value in residues
+ mouseClick(od, 0,
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(),
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click so that box straddles hidden rows
+ ypos = 44; // column value in residues
+ mouseClick(od, 0,
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(),
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /**
+ * Test setting of the box position, when there are hidden rows at the end of
+ * the alignment
+ */
+ @Test(groups = { "Functional" })
+ public void testFromMouseWithHiddenRowsAtEnd()
+ {
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ assertEquals(od.getScrollCol(), 0);
+ assertEquals(od.getScrollRow(), 0);
+
+ // hide rows at end and check updated box position is correct
+ // no changes
+ int firstHidden = 500;
+ int lastHidden = 524;
+ hideSequences(firstHidden, lastHidden);
+
+ // calculate with visible values
+ alheight = vpranges.getVisibleAlignmentHeight();
+ alwidth = vpranges.getVisibleAlignmentWidth();
+
+ boxWidth = Math.round((float) (vpranges.getEndRes()
+ - vpranges.getStartRes() + 1)
+ * od.getWidth() / alwidth);
+ boxHeight = Math.round((float) (vpranges.getEndSeq()
+ - vpranges.getStartSeq() + 1)
+ * od.getSequencesHeight() / alheight);
+
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(), 0);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click above hidden rows
+ int ypos = 40; // row 40
+ mouseClick(od, 0,
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(od.getBoxY(),
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ // click above hidden rows so box overlaps
+ // boxY, boxHeight remains same
+ ypos = 497; // row 497
+ mouseClick(od, 0,
+ Math.round((float) ypos * od.getSequencesHeight() / alheight));
+ assertEquals(od.getBoxX(), 0);
+ assertEquals(
+ od.getBoxY(),
+ Math.round((float) firstHidden * od.getSequencesHeight()
+ / alheight)
+ - boxHeight);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+ }
+
+ /*
+ * Move viewport horizontally: startRes + previous width gives new horizontal extent. Vertical extent stays the same.
+ */
+ private void moveViewportH(int startRes)
+ {
+ vpranges.setStartRes(startRes);
+ vpranges.setEndRes(startRes + viewWidth - 1);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+ }
+
+ /*
+ * Move viewport vertically: startSeq and endSeq give new vertical extent. Horizontal extent stays the same.
+ */
+ private void moveViewportV(int startSeq)
+ {
+ vpranges.setStartSeq(startSeq);
+ vpranges.setEndSeq(startSeq + viewHeight - 1);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+ }
+
+ /*
+ * Move viewport horizontally and vertically.
+ */
+ private void moveViewport(int startRes, int startSeq)
+ {
+ vpranges.setStartRes(startRes);
+ vpranges.setEndRes(startRes + viewWidth - 1);
+ vpranges.setStartSeq(startSeq);
+ vpranges.setEndSeq(startSeq + viewHeight - 1);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+ }
+
+ /*
+ * Mouse click as position x,y in overview window
+ */
+ private void mouseClick(OverviewDimensionsHideHidden od, int x, int y)
+ {
+ od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols);
+
+ // updates require an OverviewPanel to exist which it doesn't here
+ // so call setBoxPosition() as it would be called by the AlignmentPanel
+ // normally
+
+ vpranges.setStartRes(od.getScrollCol());
+ vpranges.setEndRes(od.getScrollCol() + viewWidth - 1);
+ vpranges.setStartSeq(od.getScrollRow());
+ vpranges.setEndSeq(od.getScrollRow() + viewHeight - 1);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
+ }
+
+ /*
+ * Test that the box is positioned with the top left corner at xpos, ypos
+ * and with the original width and height
+ */
+ private void testBoxIsAtClickPoint(int xpos, int ypos)
+ {
+ mouseClick(od, xpos, ypos);
+ assertEquals(od.getBoxX(), xpos);
+ assertEquals(od.getBoxY(), ypos);
+ assertEquals(od.getBoxWidth(), boxWidth);
+ assertEquals(od.getBoxHeight(), boxHeight);
+
+ }
+
+ /*
+ * Hide sequences between start and end
+ */
+ private void hideSequences(int start, int end)
+ {
+ SequenceI[] allseqs = al.getSequencesArray();
+ SequenceGroup theseSeqs = new SequenceGroup();
+
+ for (int i = start; i <= end; i++)
+ {
+ theseSeqs.addSequence(allseqs[i], false);
+ al.getHiddenSequences().hideSequence(allseqs[i]);
+ }
+
+ hiddenRepSequences.put(allseqs[start], theseSeqs);
+ }
+}
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceCollectionI;
import jalview.datamodel.SequenceGroup;
import org.testng.annotations.Test;
@Test(singleThreaded = true)
-public class OverviewDimensionsTest
+public class OverviewDimensionsShowHiddenTest
{
AlignmentI al;
- OverviewDimensions od;
+ OverviewDimensionsShowHidden od;
// cached widths and heights
int boxWidth;
Hashtable<SequenceI, SequenceCollectionI> hiddenRepSequences = new Hashtable<SequenceI, SequenceCollectionI>();
- ColumnSelection hiddenCols = new ColumnSelection();
+ HiddenColumns hiddenCols = new HiddenColumns();
@BeforeClass(alwaysRun = true)
- public void setUpJvOptionPane()
+ public void setUpAlignment()
{
// create random alignment
AlignmentGenerator gen = new AlignmentGenerator(false);
{
al.getHiddenSequences().showAll(hiddenRepSequences);
}
- hiddenCols.revealAllHiddenColumns();
+ ColumnSelection colsel = new ColumnSelection();
+ hiddenCols.revealAllHiddenColumns(colsel);
vpranges = new ViewportRanges(al);
vpranges.setStartRes(0);
viewHeight = vpranges.getEndSeq() - vpranges.getStartSeq() + 1;
viewWidth = vpranges.getEndRes() - vpranges.getStartRes() + 1;
- ColumnSelection hiddenCols = new ColumnSelection();
+ HiddenColumns hiddenCols = new HiddenColumns();
- od = new OverviewDimensions(vpranges, true);
+ od = new OverviewDimensionsShowHidden(vpranges, true);
// Initial box sizing - default path through code
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
mouseClick(od, 0, 0);
moveViewport(0, 0);
Alignment al1 = new Alignment(seqs1);
ViewportRanges props = new ViewportRanges(al1);
- OverviewDimensions od = new OverviewDimensions(props, true);
+ OverviewDimensions od = new OverviewDimensionsShowHidden(props, true);
int scaledHeight = 267;
assertEquals(od.getGraphHeight(), defaultGraphHeight);
assertEquals(od.getSequencesHeight(), scaledHeight);
Alignment al2 = new Alignment(seqs2);
props = new ViewportRanges(al2);
- od = new OverviewDimensions(props, true);
+ od = new OverviewDimensionsShowHidden(props, true);
int scaledWidth = 300;
assertEquals(od.getGraphHeight(), defaultGraphHeight);
assertEquals(od.getSequencesHeight(), maxSeqHeight);
Alignment al3 = new Alignment(seqs3);
props = new ViewportRanges(al3);
- od = new OverviewDimensions(props, true);
+ od = new OverviewDimensionsShowHidden(props, true);
assertEquals(od.getGraphHeight(), defaultGraphHeight);
assertEquals(od.getSequencesHeight(), minSeqHeight);
assertEquals(od.getWidth(), maxWidth);
Alignment al4 = new Alignment(seqs4);
props = new ViewportRanges(al4);
- od = new OverviewDimensions(props, true);
+ od = new OverviewDimensionsShowHidden(props, true);
assertEquals(od.getGraphHeight(), defaultGraphHeight);
assertEquals(od.getSequencesHeight(), maxSeqHeight);
assertEquals(od.getWidth(), minWidth);
Alignment al5 = new Alignment(seqs4);
props = new ViewportRanges(al5);
- od = new OverviewDimensions(props, false);
+ od = new OverviewDimensionsShowHidden(props, false);
assertEquals(od.getGraphHeight(), 0);
assertEquals(od.getSequencesHeight(), maxSeqHeight);
assertEquals(od.getWidth(), minWidth);
@Test(groups = { "Functional" })
public void testSetBoxFromMouseClick()
{
- od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
- vpranges);
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
assertEquals(od.getBoxWidth(), boxWidth);
@Test(groups = { "Functional" })
public void testFromMouseWithHiddenColsAtStart()
{
- od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
- vpranges);
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
assertEquals(od.getBoxWidth(), boxWidth);
int lastHiddenCol = 30;
hiddenCols.hideColumns(0, lastHiddenCol);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(),
Math.round((float) (lastHiddenCol + 1) * od.getWidth()
/ alwidth));
@Test(groups = { "Functional" })
public void testFromMouseWithHiddenColsInMiddle()
{
- od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
- vpranges);
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
assertEquals(od.getBoxWidth(), boxWidth);
int lastHidden = 73;
hiddenCols.hideColumns(firstHidden, lastHidden);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
assertEquals(od.getBoxWidth(), boxWidth);
@Test(groups = { "Functional" })
public void testFromMouseWithHiddenColsAtEnd()
{
- od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
- vpranges);
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
assertEquals(od.getBoxWidth(), boxWidth);
int firstHidden = 140;
int lastHidden = 164;
hiddenCols.hideColumns(firstHidden, lastHidden);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
assertEquals(od.getBoxWidth(), boxWidth);
assertEquals(od.getBoxX(),
Math.round((float) 3 * od.getWidth() / alwidth));
assertEquals(od.getBoxY(), 0);
- System.out.println(od.getBoxWidth());
assertEquals(od.getBoxWidth(), boxWidth);
- System.out.println(od.getBoxWidth());
assertEquals(od.getBoxHeight(), boxHeight);
// move viewport to left of hidden columns with overlap
@Test(groups = { "Functional" })
public void testFromMouseWithHiddenRowsAtStart()
{
- od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
- vpranges);
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
assertEquals(od.getBoxHeight(), boxHeight);
int lastHiddenRow = 30;
hideSequences(0, lastHiddenRow);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(),
Math.round((float) (lastHiddenRow + 1)
@Test(groups = { "Functional" })
public void testFromMouseWithHiddenRowsInMiddle()
{
- od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
- vpranges);
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
int lastHiddenRow = 54;
hideSequences(firstHiddenRow, lastHiddenRow);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
@Test(groups = { "Functional" })
public void testFromMouseWithHiddenRowsAtEnd()
{
- od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols,
- vpranges);
+ od.updateViewportFromMouse(0, 0, al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
assertEquals(od.getBoxWidth(), boxWidth);
int lastHidden = 524;
hideSequences(firstHidden, lastHidden);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
assertEquals(od.getBoxX(), 0);
assertEquals(od.getBoxY(), 0);
assertEquals(od.getBoxWidth(), boxWidth);
{
vpranges.setStartRes(startRes);
vpranges.setEndRes(startRes + viewWidth - 1);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
}
/*
{
vpranges.setStartSeq(startSeq);
vpranges.setEndSeq(startSeq + viewHeight - 1);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
}
/*
vpranges.setEndRes(startRes + viewWidth - 1);
vpranges.setStartSeq(startSeq);
vpranges.setEndSeq(startSeq + viewHeight - 1);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
}
/*
* Mouse click as position x,y in overview window
*/
- private void mouseClick(OverviewDimensions od, int x, int y)
+ private void mouseClick(OverviewDimensionsShowHidden od, int x, int y)
{
- od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols,
- vpranges);
+ od.updateViewportFromMouse(x, y, al.getHiddenSequences(), hiddenCols);
// updates require an OverviewPanel to exist which it doesn't here
// so call setBoxPosition() as it would be called by the AlignmentPanel
vpranges.setEndRes(od.getScrollCol() + viewWidth - 1);
vpranges.setStartSeq(od.getScrollRow());
vpranges.setEndSeq(od.getScrollRow() + viewHeight - 1);
- od.setBoxPosition(al.getHiddenSequences(), hiddenCols, vpranges);
+ od.setBoxPosition(al.getHiddenSequences(), hiddenCols);
}
/*
--- /dev/null
+package jalview.ws.dbsources;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import jalview.analysis.AlignSeq;
+import jalview.bin.Cache;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.DBRefSource;
+import jalview.datamodel.SequenceI;
+import jalview.ext.ensembl.EnsemblGenomes;
+import jalview.fts.api.FTSData;
+import jalview.fts.api.FTSDataColumnI;
+import jalview.fts.api.FTSRestClientI;
+import jalview.fts.core.FTSRestRequest;
+import jalview.fts.core.FTSRestResponse;
+import jalview.fts.service.uniprot.UniProtFTSRestClient;
+import jalview.ws.SequenceFetcher;
+import jalview.ws.seqfetcher.DbSourceProxy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * A class to verify that remotely fetched data has an expected format and can
+ * be successfully processed by Jalview. This is intended as a first line of
+ * defence and early warning of service affecting changes to data fetched
+ * externally.
+ * <p>
+ * This is class is not intended to cover remote services e.g. alignment. Nor
+ * should it duplicate tests already provided by other classes (such as
+ * PDBFTSRestClientTest). Or maybe we will relocate those tests here...
+ */
+public class RemoteFormatTest
+{
+ SequenceFetcher sf;
+
+ @BeforeTest(alwaysRun = true)
+ public void setUp() throws Exception
+ {
+ Cache.loadProperties("test/jalview/io/testProps.jvprops");
+ // ensure 'add annotation from structure' is selected
+ Cache.applicationProperties.setProperty("STRUCT_FROM_PDB",
+ Boolean.TRUE.toString());
+ Cache.applicationProperties.setProperty("ADD_SS_ANN",
+ Boolean.TRUE.toString());
+
+ sf = new SequenceFetcher(false);
+ }
+
+ @DataProvider(name = "AccessionData")
+ protected Object[][] getAccessions()
+ {
+ return new Object[][] { { DBRefSource.UNIPROT, "P30419" },
+ { DBRefSource.PDB, "1QIP" }, { DBRefSource.EMBL, "X53828" },
+ { DBRefSource.EMBLCDS, "CAA37824" },
+ { DBRefSource.ENSEMBL, "ENSG00000157764" },
+ { new EnsemblGenomes().getDbSource(), "DDB_G0283883" },
+ { new PfamFull().getDbSource(), "PF03760" },
+ { new PfamSeed().getDbSource(), "PF03760" },
+ { new RfamSeed().getDbSource(), "RF00014" } };
+ }
+
+ @Test(groups = "Network", dataProvider = "AccessionData")
+ public void testFetchAccession(String dbSource, String accessionId)
+ throws Exception
+ {
+ System.out.println("Fetching " + accessionId + " from " + dbSource);
+ List<DbSourceProxy> sps = sf.getSourceProxy(dbSource);
+ assertFalse(sps.isEmpty());
+ AlignmentI al = sps.get(0).getSequenceRecords(accessionId);
+ assertNotNull(al);
+ assertTrue(al.getHeight() > 0);
+ SequenceI sq = al.getSequenceAt(0);
+ // suppress this check as only Uniprot and PDB acquire PDB refs
+ // assertTrue(sq.getAllPDBEntries().size() > 0, "No PDBEntry on sequence.");
+ assertTrue(sq.getDBRefs().length > 0, "No DBRef on sequence.");
+ // suppress this test as only certain databases provide 'primary' dbrefs
+ // assertFalse(sq.getPrimaryDBRefs().isEmpty());
+ int length = AlignSeq.extractGaps("-. ", sq.getSequenceAsString())
+ .length();
+ assertEquals(sq.getEnd() - sq.getStart() + 1, length,
+ "Sequence start/end doesn't match number of residues in sequence");
+ }
+
+ @Test(groups = { "Network" })
+ public void testUniprotFreeTextSearch() throws Exception
+ {
+ List<FTSDataColumnI> wantedFields = new ArrayList<FTSDataColumnI>();
+ FTSRestClientI client = UniProtFTSRestClient.getInstance();
+ wantedFields.add(client.getDataColumnByNameOrCode("id"));
+ wantedFields.add(client.getDataColumnByNameOrCode("entry name"));
+ wantedFields.add(client.getDataColumnByNameOrCode("organism"));
+ wantedFields.add(client.getDataColumnByNameOrCode("reviewed")); // Status
+ wantedFields.add(client.getDataColumnByNameOrCode("length"));
+
+ FTSRestRequest request = new FTSRestRequest();
+ request.setAllowEmptySeq(false);
+ request.setResponseSize(100);
+ request.setFieldToSearchBy("Search All");
+ request.setSearchTerm("metanephrops"); // lobster!
+ request.setWantedFields(wantedFields);
+
+ FTSRestResponse response;
+ response = client.executeRequest(request);
+ assertTrue(response.getNumberOfItemsFound() > 20);
+ assertTrue(response.getSearchSummary() != null);
+ assertTrue(response.getSearchSummary().size() > 20);
+ // verify we successfully filtered out the header row (JAL-2485)
+ FTSData header = response.getSearchSummary().iterator().next();
+ assertFalse(
+ header.getSummaryData()[0].toString().equalsIgnoreCase("Entry"),
+ "Failed to filter out summary header row");
+ }
+}
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-@Test(groups = { "External" })
+/*
+ * All methods in this class are set to the Network group because setUpBeforeClass will fail
+ * if there is no network.
+ */
+@Test(singleThreaded = true)
public class DisorderAnnotExportImport
{
public static jalview.gui.AlignFrame af = null;
- @BeforeClass(inheritGroups = true)
+ @BeforeClass(alwaysRun = true)
public static void setUpBeforeClass() throws Exception
{
Cache.loadProperties("test/jalview/io/testProps.jvprops");
Cache.initLogger();
disc = JalviewJabawsTestUtils.getJabawsDiscoverer();
+
+ while (disc.isRunning())
+ {
+ // don't get services until discoverer has finished
+ Thread.sleep(100);
+ }
+
iupreds = new ArrayList<Jws2Instance>();
for (Jws2Instance svc : disc.getServices())
{
/**
* test for patches to JAL-1294
*/
- @Test
+ @Test(groups = { "External", "Network" })
public void testDisorderAnnotExport()
{
disorderClient = new AADisorderClient(iupreds.get(0), af, null, null);
DataSourceType.PASTE));
// test for consistency in io
- StockholmFileTest.testAlignmentEquivalence(al, al_new, true);
+ StockholmFileTest.testAlignmentEquivalence(al, al_new, true, false,
+ false);
return;
} catch (Exception e)
{
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import compbio.metadata.Argument;
public static jalview.gui.AlignFrame af = null;
- @BeforeClass(alwaysRun = true)
+ @BeforeGroups(groups = { "Network" })
public static void setUpBeforeClass() throws Exception
{
Cache.loadProperties("test/jalview/io/testProps.jvprops");
}
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" }, enabled = false)
public void testJPredStructOneSeqOnly()
{
af.selectAllSequenceMenuItem_actionPerformed(null);
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" }, enabled = false)
public void testJPredStructExport()
{
DataSourceType.PASTE));
// test for consistency in io
- StockholmFileTest.testAlignmentEquivalence(al, al_new, false);
+ StockholmFileTest.testAlignmentEquivalence(al, al_new, false, false,
+ false);
return;
} catch (Exception e)
{
+ "\nCouldn't complete Annotation file roundtrip input/output/input test.");
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" }, enabled = false)
public void testJpredwsSettingsRecovery()
{
Assert.fail("not implemnented");
import compbio.metadata.Argument;
import compbio.metadata.WrongParameterException;
+/*
+ * All methods in this class are set to the Network group because setUpBeforeClass will fail
+ * if there is no network.
+ */
+@Test(singleThreaded = true)
public class RNAStructExportImport
{
Cache.initLogger();
disc = JalviewJabawsTestUtils.getJabawsDiscoverer(false);
+ while (disc.isRunning())
+ {
+ // don't get services until discoverer has finished
+ Thread.sleep(100);
+ }
+
for (Jws2Instance svc : disc.getServices())
{
}
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testRNAAliFoldValidStructure()
{
}
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testRNAStructExport()
{
AlignmentI orig_alig = af.getViewport().getAlignment();
- testAnnotationFileIO("Testing RNAalifold Annotation IO", orig_alig);
+ verifyAnnotationFileIO("Testing RNAalifold Annotation IO", orig_alig);
}
- public static void testAnnotationFileIO(String testname, AlignmentI al)
+ static void verifyAnnotationFileIO(String testname, AlignmentI al)
{
try
{
DataSourceType.PASTE));
// test for consistency in io
- StockholmFileTest.testAlignmentEquivalence(al, al_new, false);
+ StockholmFileTest.testAlignmentEquivalence(al, al_new, false, false,
+ false);
return;
} catch (Exception e)
{
+ "\nCouldn't complete Annotation file roundtrip input/output/input test.");
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testRnaalifoldSettingsRecovery()
{
List<Argument> opts = new ArrayList<Argument>();
import compbio.metadata.PresetManager;
import compbio.metadata.WrongParameterException;
+/*
+ * All methods in this class are set to the Network group because setUpBeforeClass will fail
+ * if there is no network.
+ */
+@Test(singleThreaded = true)
public class ParameterUtilsTest
{
disc = JalviewJabawsTestUtils.getJabawsDiscoverer();
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testWriteParameterSet() throws WrongParameterException
{
for (Jws2Instance service : disc.getServices())
|| serviceTests.contains(service.serviceType.toLowerCase());
}
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testCopyOption()
{
for (Jws2Instance service : disc.getServices())
/**
*/
- @Test(groups = { "Functional" })
+ @Test(groups = { "Network" })
public void testCopyParameter()
{
for (Jws2Instance service : disc.getServices())
Assert.assertNull(entityP);
}
+
+ @Test(groups = { "Network" })
+ public void getLeadingIntegerFromString()
+ {
+ Assert.assertEquals(
+ SiftsClient.getLeadingIntegerValue("1234abcd", -1), 1234);
+ Assert.assertEquals(
+ SiftsClient.getLeadingIntegerValue("1234", -1),
+ 1234);
+ Assert.assertEquals(
+ SiftsClient.getLeadingIntegerValue("abcd", -1), -1);
+ Assert.assertEquals(
+ SiftsClient.getLeadingIntegerValue("abcd1234", -1), -1);
+ Assert.assertEquals(
+ SiftsClient.getLeadingIntegerValue("None", -1), -1);
+ Assert.assertEquals(
+ SiftsClient.getLeadingIntegerValue("Null", -1), -1);
+ }
}