<classpathentry kind="lib" path="lib/jdas-1.0.4.jar"/>
<classpathentry kind="lib" path="lib/spring-core-3.0.5.RELEASE.jar"/>
<classpathentry kind="lib" path="lib/spring-web-3.0.5.RELEASE.jar"/>
- <classpathentry kind="lib" path="lib/groovy-all-1.8.2.jar"/>
+ <classpathentry kind="lib" path="/Users/jprocter/git/jalview/lib/groovy-all-2.4.6.jar"/>
<classpathentry kind="lib" path="lib/min-jabaws-client-2.1.0.jar" sourcepath="/clustengine"/>
<classpathentry kind="lib" path="lib/json_simple-1.1.jar" sourcepath="/Users/jimp/Downloads/json_simple-1.1-all.zip"/>
<classpathentry kind="lib" path="lib/slf4j-api-1.7.7.jar"/>
commons-logging-1.1.1.jar
commons-logging.jar
commons-net-3.3.jar
+groovy-all-2.4.6-indy.jar APL 2.0 License - downloaded and extracted from https://dl.bintray.com/groovy/maven/apache-groovy-binary-2.4.6.zip
httpclient-4.0.3.jar
httpcore-4.0.1.jar
httpmime-4.0.3.jar
</title>
<body>
<h1>
-Adding Groovy Support to Jalview
+Groovy Support in Jalview
</h1>
<p>
-There is currently no scripting language
-extension within Jalview, in part because a
-scripting API has not yet been developed.
-</p>
-<p>It is, however, really easy to embed scripting
-engines like groovy. If groovy is detected on the
-classpath, a new menu entry on the Desktop's Tools
-menu will open the GroovyShell.
+ <a href="http://www.groovy-lang.org">Groovy</a> has been bundled with the Jalview desktop since circa 2012. The program supports interactive execution of groovy scripts via the Groovy Console, and command line execution via the '-groovy' option. The main source for documentation about Groovy in Jalview is the <a href="http://www.jalview.org/help/html/features/groovy.html">online help pages</a>.
</p>
<p>Here are some scripts to get you started:</p>
<ul><li>Getting the title, alignment and first sequence from the current alignFrame<br>
</pre>
</li>
</ul>
-<h1>Getting Groovy...</h1>
-<p>
-You need the core groovy jars which include the GroovyShell. The easiest way of doing
-this is to add the groovy-all-*.jar to the lib directory whose path is given in the java.ext.dirs property.</p>
-<p>The is obtained from the <em>embedded</em> directory within the <a
-href="http://dist.codehaus.org/groovy/distributions"/>groovy distribution</a>).
-</p>
<h2>TODO</h2>
<p>
Using Java class methods from Groovy is straightforward, but currently, there isn't a set of easy to use methods for the jalview objects. A Jalview Scripting API needs to be developed to make this easier.</p>
--- /dev/null
+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
+ * Modify this example as required to count by column any desired value that can be
+ * derived from the residue and sequence features at each position of 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 counts residues with a Pfam feature annotation
+ * 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, residueTester, featureCounter ->
+ [
+ getName: { name },
+ getDescription: { desc },
+ getMinColour: { [0, 255, 255] }, // cyan
+ getMaxColour: { [0, 0, 255] }, // blue
+ count:
+ { res, feats ->
+ def c = 0
+ if (residueTester.call(res))
+ {
+ if (featureCounter.call(feats))
+ {
+ c++
+ }
+ }
+ c
+ }
+ ] as FeatureCounterI
+}
+
+/*
+ * Define annotation that counts any residue with Pfam domain annotation
+ */
+def pfamAnnotation = getColumnCounter("Pfam", "Count of residues with Pfam domain annotation", {true}, hasPfam)
+
+/*
+ * Define annotation 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
+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)
<tocitem text="PDB Sequence Fetcher" target="pdbfetcher" />
<tocitem text="PDB Structure Chooser" target="pdbchooser" />
<tocitem text="Chimera Viewer" target="chimera" />
- <tocitem text="Select columns by annotation" target="selectcolbyannot" />
+ <tocitem text="Select Columns by Annotation" target="selectcolbyannot" />
<tocitem text="Latest Release Notes" target="release"/>
</tocitem>
<tocitem text="Viewing Trees" target="treeviewer" expand="false" />
<tocitem text="Fetching Sequences" target="seqfetch" />
- <tocitem text="Select columns by annotation" target="selectcolbyannot" />
+ <tocitem text="Select Columns by Annotation" target="selectcolbyannot" />
<tocitem text="Nucleic Acid Support" target="nucleicAcids" expand="false">
<tocitem text="Viewing RNA structure" target="varna" />
<tocitem text="Consensus" target="calcs.consensus" />
<tocitem text="RNA Structure Consensus" target="calcs.alstrconsensus" />
<tocitem text="Annotations File Format" target="annotations.fileformat" />
- <tocitem text="Select Column by Annotation" target="calcs.annotation" />
+ <tocitem text="Select Columns by Annotation" target="selectcolbyannot" />
</tocitem>
<tocitem text="3D Structure Data" target="viewingpdbs" expand="false">
<tocitem text="PDB Sequence Fetcher" target="pdbfetcher" />
<strong>The Groovy Shell</strong>
</p>
<p>
- <a href="http://groovy.codehaus.org/">Groovy</a> is an "<em>agile
+ <a href="http://www.groovy-lang.org/">Groovy</a> is an "<em>agile
and dynamic language for the Java platform</em>". The groovy
scripting language makes it extremely easy to programmatically
interact with Java programs, in much the same way that Javascript is
page.
</p>
<p>
- <strong><em>Getting Groovy...</em> </strong><br> Jalview Groovy
- support is only possible if the core groovy jars which include the
- GroovyShell are present on the CLASSPATH when Jalview is started.
- </p>
- <p>
- The jars are obtained from the <em>embedded</em> directory within
- the <a href="http://dist.codehaus.org/groovy/distributions">groovy
- distribution</a>. The easiest way of adding them to the Jalview
- classpath is to download and build Jalview from its source
- distribution, and then add the groovy-all-*.jar to the lib directory
- whose path is given in the java.ext.dirs property.
- </p>
- <p>
- <strong>Opening Jalview's Groovy Console</strong><br>If groovy
- is available, then the <strong>Tools→Groovy
- Console...</strong> menu entry will be available from the Jalview Desktop's
- drop-down menu. Selecting this will open the <a
- href="http://groovy.codehaus.org/Groovy+Console"
- >Groovy Console</a> which allows you to interactively execute Groovy
+ <strong><em>Getting Groovy...</em> </strong><br> Jalview comes with
+ an embedded installation of Groovy. All you need is to select <strong>Tools→Groovy
+ Console...</strong> menu option from the Jalview Desktop's
+ drop-down menu. After a short pause, you should then see the <a
+ href="http://groovy-lang.org/groovyconsole.html"
+ >Groovy Console</a> appear. This allows you to interactively execute Groovy
scripts within the Jalview run-time environment.
</p>
<p>
info.error_creating_file = Error creating {0} file.
exception.outofmemory_loading_mmcif_file = Out of memory loading mmCIF File
info.error_creating_file = Error creating {0} file.
+label.run_groovy = Run Groovy console script
+label.run_groovy_tip = Run the script in the Groovy console over this alignment
+label.couldnt_run_groovy_script = Failed to run Groovy script
label.uniprot_sequence_fetcher = UniProt Sequence Fetcher
\ No newline at end of file
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JRadioButtonMenuItem;
-import javax.swing.SwingUtilities;
public class PDBViewer extends JInternalFrame implements Runnable
{
@Override
public void mousePressed(MouseEvent evt)
{
- if (evt.isControlDown()
- || SwingUtilities.isRightMouseButton(evt))
+ if (evt.isPopupTrigger())
{
radioItem.removeActionListener(radioItem.getActionListeners()[0]);
*/
package jalview.analysis;
+import static jalview.io.gff.GffConstants.CLINICAL_SIGNIFICANCE;
+
import jalview.datamodel.AlignedCodon;
import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.Alignment;
import jalview.util.Comparison;
import jalview.util.MapList;
import jalview.util.MappingUtils;
-import jalview.util.StringUtils;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
public class AlignmentUtils
{
+ private static final String SEQUENCE_VARIANT = "sequence_variant:";
+ private static final String ID = "ID";
+
+ /**
+ * A data model to hold the 'normal' base value at a position, and an optional
+ * sequence variant feature
+ */
+ static class DnaVariant
+ {
+ String base;
+
+ SequenceFeature variant;
+
+ DnaVariant(String nuc)
+ {
+ base = nuc;
+ }
+
+ DnaVariant(String nuc, SequenceFeature var)
+ {
+ base = nuc;
+ variant = var;
+ }
+ }
+
/**
* given an existing alignment, create a new alignment including all, or up to
* flankSize additional symbols from each sequence's dataset sequence
* /ENSP00000288602?feature=transcript_variation;content-type=text/xml
* which would be a bit slower but possibly more reliable
*/
- LinkedHashMap<Integer, List<String[][]>> variants = buildDnaVariantsMap(
+
+ /*
+ * build a map with codon variations for each potentially varying peptide
+ */
+ LinkedHashMap<Integer, List<DnaVariant>[]> variants = buildDnaVariantsMap(
dnaSeq, dnaToProtein);
/*
* scan codon variations, compute peptide variants and add to peptide sequence
*/
int count = 0;
- for (Entry<Integer, List<String[][]>> variant : variants.entrySet())
+ for (Entry<Integer, List<DnaVariant>[]> variant : variants.entrySet())
{
int peptidePos = variant.getKey();
- List<String[][]> codonVariants = variant.getValue();
- String residue = String.valueOf(peptide.getCharAt(peptidePos - 1)); // 0-based
- for (String[][] codonVariant : codonVariants)
- {
- List<String> peptideVariants = computePeptideVariants(codonVariant,
- residue);
- if (!peptideVariants.isEmpty())
- {
- String desc = residue
- + "->" // include canonical residue in description
- + StringUtils
- .listToDelimitedString(peptideVariants, ", ");
- SequenceFeature sf = new SequenceFeature(
- SequenceOntologyI.SEQUENCE_VARIANT, desc, peptidePos,
- peptidePos, 0f, null);
- peptide.addSequenceFeature(sf);
- count++;
- }
- }
+ List<DnaVariant>[] codonVariants = variant.getValue();
+ count += computePeptideVariants(peptide, peptidePos, codonVariants);
}
/*
- * ugly sort to get sequence features in start position order
+ * sort to get sequence features in start position order
* - would be better to store in Sequence as a TreeSet or NCList?
*/
Arrays.sort(peptide.getSequenceFeatures(),
}
/**
- * Builds a map whose key is position in the protein sequence, and value is an
- * array of all variants for the coding codon positions
+ * Computes non-synonymous peptide variants from codon variants and adds them
+ * as sequence_variant features on the protein sequence (one feature per
+ * allele variant). Selected attributes (variant id, clinical significance)
+ * are copied over to the new features.
+ *
+ * @param peptide
+ * the protein sequence
+ * @param peptidePos
+ * the position to compute peptide variants for
+ * @param codonVariants
+ * a list of dna variants per codon position
+ * @return the number of features added
+ */
+ static int computePeptideVariants(SequenceI peptide, int peptidePos,
+ List<DnaVariant>[] codonVariants)
+ {
+ String residue = String.valueOf(peptide.getCharAt(peptidePos - 1));
+ int count = 0;
+ String base1 = codonVariants[0].get(0).base;
+ String base2 = codonVariants[1].get(0).base;
+ String base3 = codonVariants[2].get(0).base;
+
+ /*
+ * variants in first codon base
+ */
+ for (DnaVariant var : codonVariants[0])
+ {
+ if (var.variant != null)
+ {
+ String alleles = (String) var.variant.getValue("alleles");
+ if (alleles != null)
+ {
+ for (String base : alleles.split(","))
+ {
+ String codon = base + base2 + base3;
+ if (addPeptideVariant(peptide, peptidePos, residue, var, codon))
+ {
+ count++;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * variants in second codon base
+ */
+ for (DnaVariant var : codonVariants[1])
+ {
+ if (var.variant != null)
+ {
+ String alleles = (String) var.variant.getValue("alleles");
+ if (alleles != null)
+ {
+ for (String base : alleles.split(","))
+ {
+ String codon = base1 + base + base3;
+ if (addPeptideVariant(peptide, peptidePos, residue, var, codon))
+ {
+ count++;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * variants in third codon base
+ */
+ for (DnaVariant var : codonVariants[2])
+ {
+ if (var.variant != null)
+ {
+ String alleles = (String) var.variant.getValue("alleles");
+ if (alleles != null)
+ {
+ for (String base : alleles.split(","))
+ {
+ String codon = base1 + base2 + base;
+ if (addPeptideVariant(peptide, peptidePos, residue, var, codon))
+ {
+ count++;
+ }
+ }
+ }
+ }
+ }
+
+ return count;
+ }
+
+ /**
+ * Helper method that adds a peptide variant feature, provided the given codon
+ * translates to a value different to the current residue (is a non-synonymous
+ * variant). ID and clinical_significance attributes of the dna variant (if
+ * present) are copied to the new feature.
+ *
+ * @param peptide
+ * @param peptidePos
+ * @param residue
+ * @param var
+ * @param codon
+ * @return true if a feature was added, else false
+ */
+ static boolean addPeptideVariant(SequenceI peptide, int peptidePos,
+ String residue, DnaVariant var, String codon)
+ {
+ /*
+ * get peptide translation of codon e.g. GAT -> D
+ * note that variants which are not single alleles,
+ * e.g. multibase variants or HGMD_MUTATION etc
+ * are currently ignored here
+ */
+ String trans = codon.contains("-") ? "-"
+ : (codon.length() > 3 ? null : ResidueProperties
+ .codonTranslate(codon));
+ if (trans != null && !trans.equals(residue))
+ {
+ String desc = residue + "->" + trans;
+ // set score to 0f so 'graduated colour' option is offered! JAL-2060
+ SequenceFeature sf = new SequenceFeature(
+ SequenceOntologyI.SEQUENCE_VARIANT, desc, peptidePos,
+ peptidePos, 0f, null);
+ StringBuilder attributes = new StringBuilder(32);
+ String id = (String) var.variant.getValue(ID);
+ if (id != null)
+ {
+ if (id.startsWith(SEQUENCE_VARIANT))
+ {
+ id = id.substring(SEQUENCE_VARIANT.length());
+ }
+ sf.setValue(ID, id);
+ attributes.append(ID).append("=").append(id);
+ // TODO handle other species variants
+ StringBuilder link = new StringBuilder(32);
+ try
+ {
+ link.append(desc).append(" ").append(id)
+ .append("|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=")
+ .append(URLEncoder.encode(id, "UTF-8"));
+ sf.addLink(link.toString());
+ } catch (UnsupportedEncodingException e)
+ {
+ // as if
+ }
+ }
+ String clinSig = (String) var.variant
+ .getValue(CLINICAL_SIGNIFICANCE);
+ if (clinSig != null)
+ {
+ sf.setValue(CLINICAL_SIGNIFICANCE, clinSig);
+ attributes.append(";").append(CLINICAL_SIGNIFICANCE).append("=")
+ .append(clinSig);
+ }
+ peptide.addSequenceFeature(sf);
+ if (attributes.length() > 0)
+ {
+ sf.setAttributes(attributes.toString());
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Builds a map whose key is position in the protein sequence, and value is a
+ * list of the base and all variants for each corresponding codon position
*
* @param dnaSeq
* @param dnaToProtein
* @return
*/
- static LinkedHashMap<Integer, List<String[][]>> buildDnaVariantsMap(
+ static LinkedHashMap<Integer, List<DnaVariant>[]> buildDnaVariantsMap(
SequenceI dnaSeq, MapList dnaToProtein)
{
/*
- * map from peptide position to all variant features of the codon for it
- * LinkedHashMap ensures we add the peptide features in sequence order
+ * map from peptide position to all variants of the codon which codes for it
+ * LinkedHashMap ensures we keep the peptide features in sequence order
*/
- LinkedHashMap<Integer, List<String[][]>> variants = new LinkedHashMap<Integer, List<String[][]>>();
+ LinkedHashMap<Integer, List<DnaVariant>[]> variants = new LinkedHashMap<Integer, List<DnaVariant>[]>();
SequenceOntologyI so = SequenceOntologyFactory.getInstance();
SequenceFeature[] dnaFeatures = dnaSeq.getSequenceFeatures();
continue;
}
int peptidePosition = mapsTo[0];
- List<String[][]> codonVariants = variants.get(peptidePosition);
+ List<DnaVariant>[] codonVariants = variants.get(peptidePosition);
if (codonVariants == null)
{
- codonVariants = new ArrayList<String[][]>();
+ codonVariants = new ArrayList[3];
+ codonVariants[0] = new ArrayList<DnaVariant>();
+ codonVariants[1] = new ArrayList<DnaVariant>();
+ codonVariants[2] = new ArrayList<DnaVariant>();
variants.put(peptidePosition, codonVariants);
}
lastCodon = codon;
/*
- * save nucleotide (and this variant) for each codon position
+ * save nucleotide (and any variant) for each codon position
*/
- String[][] codonVariant = new String[3][];
for (int codonPos = 0; codonPos < 3; codonPos++)
{
String nucleotide = String.valueOf(
dnaSeq.getCharAt(codon[codonPos] - dnaStart))
.toUpperCase();
- if (codonVariant[codonPos] == null)
+ List<DnaVariant> codonVariant = codonVariants[codonPos];
+ if (codon[codonPos] == dnaCol)
{
- /*
- * record current dna base
- */
- codonVariant[codonPos] = new String[] { nucleotide };
+ if (!codonVariant.isEmpty()
+ && codonVariant.get(0).variant == null)
+ {
+ /*
+ * already recorded base value, add this variant
+ */
+ codonVariant.get(0).variant = sf;
+ }
+ else
+ {
+ /*
+ * add variant with base value
+ */
+ codonVariant.add(new DnaVariant(nucleotide, sf));
+ }
}
- if (codon[codonPos] == dnaCol)
+ else if (codonVariant.isEmpty())
{
/*
- * add alleles to dna base (and any previously found alleles)
+ * record (possibly non-varying) base value
*/
- String[] known = codonVariant[codonPos];
- String[] dnaVariants = new String[alleles.length + known.length];
- System.arraycopy(known, 0, dnaVariants, 0, known.length);
- System.arraycopy(alleles, 0, dnaVariants, known.length,
- alleles.length);
- codonVariant[codonPos] = dnaVariants;
+ codonVariant.add(new DnaVariant(nucleotide));
}
}
- codonVariants.add(codonVariant);
}
}
return variants;
}
/**
- * Returns a sorted, non-redundant list of all peptide translations generated
- * by the given dna variants, excluding the current residue value
- *
- * @param codonVariants
- * an array of base values (acgtACGT) for codon positions 1, 2, 3
- * @param residue
- * the current residue translation
- * @return
- */
- static List<String> computePeptideVariants(String[][] codonVariants,
- String residue)
- {
- List<String> result = new ArrayList<String>();
- for (String base1 : codonVariants[0])
- {
- for (String base2 : codonVariants[1])
- {
- for (String base3 : codonVariants[2])
- {
- String codon = base1 + base2 + base3;
- /*
- * get peptide translation of codon e.g. GAT -> D
- * note that variants which are not single alleles,
- * e.g. multibase variants or HGMD_MUTATION etc
- * are ignored here
- */
- String peptide = codon.contains("-") ? "-"
- : (codon.length() > 3 ? null : ResidueProperties
- .codonTranslate(codon));
- if (peptide != null && !result.contains(peptide)
- && !peptide.equalsIgnoreCase(residue))
- {
- result.add(peptide);
- }
- }
- }
- }
-
- /*
- * sort alphabetically with STOP at the end
- */
- Collections.sort(result, new Comparator<String>()
- {
-
- @Override
- public int compare(String o1, String o2)
- {
- if ("STOP".equals(o1))
- {
- return 1;
- }
- else if ("STOP".equals(o2))
- {
- return -1;
- }
- else
- {
- return o1.compareTo(o2);
- }
- }
- });
- return result;
- }
-
- /**
* Makes an alignment with a copy of the given sequences, adding in any
* non-redundant sequences which are mapped to by the cross-referenced
* sequences.
import jalview.api.analysis.ScoreModelI;
import jalview.api.analysis.ViewBasedAnalysisI;
import jalview.datamodel.AlignmentView;
+import jalview.datamodel.SeqCigar;
import jalview.datamodel.SequenceFeature;
-import jalview.datamodel.SequenceI;
-import jalview.util.Comparison;
import java.util.ArrayList;
import java.util.Hashtable;
{
int nofeats = 0;
List<String> dft = fr.getDisplayedFeatureTypes();
-
nofeats = dft.size();
-
- SequenceI[] sequenceString = seqData.getVisibleAlignment(
- Comparison.GapChars.charAt(0)).getSequencesArray();
- int noseqs = sequenceString.length;
- int cpwidth = seqData.getWidth();
+ SeqCigar[] seqs = seqData.getSequences();
+ int noseqs = seqs.length;
+ int cpwidth = 0;// = seqData.getWidth();
float[][] distance = new float[noseqs][noseqs];
if (nofeats == 0)
{
}
return distance;
}
- float max = 0;
- for (int cpos = 0; cpos < cpwidth; cpos++)
+ // need to get real position for view position
+ int[] viscont = seqData.getVisibleContigs();
+ for (int vc = 0; vc < viscont.length; vc += 2)
{
- // 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>();
- List<SequenceFeature> sfs = fr.findFeaturesAtRes(sequenceString[i],
- sequenceString[i].findPosition(cpos));
- for (SequenceFeature sf : sfs)
- {
- types.put(sf.getType(), sf);
- }
- sfap.add(types);
- }
- for (int i = 0; i < (noseqs - 1); i++)
+
+ for (int cpos = viscont[vc]; cpos <= viscont[vc + 1]; cpos++)
{
- if (cpos == 0)
- {
- distance[i][i] = 0f;
- }
- for (int j = i + 1; j < noseqs; j++)
+ 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++)
{
- 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())
+ Hashtable<String, SequenceFeature> types = new Hashtable<String, SequenceFeature>();
+ int spos = seqs[i].findPosition(cpos);
+ if (spos != -1)
{
- fk = fj;
+ List<SequenceFeature> sfs = fr.findFeaturesAtRes(
+ seqs[i].getRefSeq(), spos);
+ for (SequenceFeature sf : sfs)
+ {
+ types.put(sf.getType(), sf);
+ }
}
- else
+ sfap.add(types);
+ }
+ for (int i = 0; i < (noseqs - 1); i++)
+ {
+ if (cpos == 0)
{
- fk = fi;
- fi = fj;
+ distance[i][i] = 0f;
}
- for (String k : fi.keySet())
+ for (int j = i + 1; j < noseqs; j++)
{
- SequenceFeature sfj = fk.get(k);
- if (sfj != null)
+ 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())
{
- sfcommon++;
+ SequenceFeature sfj = fk.get(k);
+ if (sfj != null)
+ {
+ sfcommon++;
+ }
}
+ distance[i][j] += (fi.size() + fk.size() - 2f * sfcommon);
+ distance[j][i] += distance[i][j];
}
- distance[i][j] += (fi.size() + fk.size() - 2f * sfcommon);
- distance[j][i] += distance[i][j];
}
}
}
import jalview.datamodel.AlignmentAnnotation;
+/**
+ * Interface describing a worker that calculates alignment annotation(s). The
+ * main (re-)calculation should be performed by the inherited run() method.
+ */
public interface AlignCalcWorkerI extends Runnable
{
-
+ /**
+ * Answers true if this worker updates the given annotation (regardless of its
+ * current state)
+ *
+ * @param annot
+ * @return
+ */
public boolean involves(AlignmentAnnotation annot);
+ /**
+ * Updates the display of calculated annotation values (does not recalculate
+ * the values). This allows for quick redraw of annotations when display
+ * settings are changed.
+ */
public void updateAnnotation();
- void removeOurAnnotation();
+ /**
+ * Removes any annotation managed by this worker from the alignment
+ */
+ void removeAnnotation();
}
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.Enumeration;
-import java.util.Hashtable;
import java.util.List;
+import java.util.Map;
import java.util.Vector;
public class FeatureSettings extends Panel implements ItemListener,
60);
}
- protected void popupSort(final MyCheckbox check, final Hashtable minmax,
+ protected void popupSort(final MyCheckbox check,
+ final Map<String, float[][]> minmax,
int x, int y)
{
final String type = check.type;
men.add(dens);
if (minmax != null)
{
- final Object typeMinMax = minmax.get(type);
+ final float[][] typeMinMax = minmax.get(type);
/*
* final java.awt.CheckboxMenuItem chb = new
* java.awt.CheckboxMenuItem("Vary Height"); // this is broken at the
*
* }); men.add(chb);
*/
- if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
+ if (typeMinMax != null && typeMinMax[0] != null)
{
// graduated colourschemes for those where minmax exists for the
// positional features
{
SequenceFeature[] tmpfeatures;
String group = null, type;
- Vector visibleChecks = new Vector();
+ Vector<String> visibleChecks = new Vector<String>();
AlignmentI alignment = av.getAlignment();
for (int i = 0; i < alignment.getHeight(); i++)
{
// now add checkboxes which should be visible,
// if they have not already been added
- Enumeration en = visibleChecks.elements();
+ Enumeration<String> en = visibleChecks.elements();
while (en.hasMoreElements())
{
}
/**
+ *
+ * @param column
+ * @return position in sequence for column (or -1 if no match state exists)
+ */
+ public int findPosition(int column)
+ {
+ int w = 0, ew, p = refseq.findPosition(start);
+ if (column < 0)
+ {
+ return -1;
+ }
+ if (range != null)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ if (operation[i] == M || operation[i] == D)
+ {
+ p += range[i];
+ }
+ if (operation[i] == M || operation[i] == I)
+ {
+ ew = w + range[i];
+ if (column < ew)
+ {
+ if (operation[i] == I)
+ {
+ return -1;
+ }
+ return p - (ew - column);
+ }
+ w = ew;
+ }
+ }
+ }
+ return -1;
+ }
+
+ /**
* Returns sequence as a string with cigar operations applied to it
*
* @return String
*/
+ @Override
public String getSequenceString(char GapChar)
{
return (length == 0) ? "" : (String) getSequenceAndDeletions(
// private key for Phase designed not to conflict with real GFF data
private static final String PHASE = "!Phase";
+ /*
+ * ATTRIBUTES is reserved for the GFF 'column 9' data, formatted as
+ * name1=value1;name2=value2,value3;...etc
+ */
private static final String ATTRIBUTES = "ATTRIBUTES";
public int begin;
}
}
+ /**
+ * Constructor including a Status value
+ *
+ * @param type
+ * @param desc
+ * @param status
+ * @param begin
+ * @param end
+ * @param featureGroup
+ */
public SequenceFeature(String type, String desc, String status,
int begin, int end, String featureGroup)
{
+ this(type, desc, begin, end, featureGroup);
+ setStatus(status);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param type
+ * @param desc
+ * @param begin
+ * @param end
+ * @param featureGroup
+ */
+ SequenceFeature(String type, String desc, int begin, int end,
+ String featureGroup)
+ {
this.type = type;
this.description = desc;
- setValue(STATUS, status);
this.begin = begin;
this.end = end;
this.featureGroup = featureGroup;
}
+ /**
+ * Constructor including a score value
+ *
+ * @param type
+ * @param desc
+ * @param begin
+ * @param end
+ * @param score
+ * @param featureGroup
+ */
public SequenceFeature(String type, String desc, int begin, int end,
float score, String featureGroup)
{
- this.type = type;
- this.description = desc;
- this.begin = begin;
- this.end = end;
+ this(type, desc, begin, end, featureGroup);
this.score = score;
- this.featureGroup = featureGroup;
}
/**
import jalview.io.FileParse;
import jalview.io.gff.SequenceOntologyFactory;
import jalview.io.gff.SequenceOntologyI;
+import jalview.util.Comparison;
import jalview.util.DBRefUtils;
import jalview.util.MapList;
{
complement.append(",");
}
- if ("HGMD_MUTATION".equalsIgnoreCase(allele))
+
+ /*
+ * some 'alleles' are actually descriptive terms
+ * e.g. HGMD_MUTATION, PhenCode_variation
+ * - we don't want to 'reverse complement' these
+ */
+ if (!Comparison.isNucleotideSequence(allele, true))
{
complement.append(allele);
}
else
{
- char[] alleles = allele.toCharArray();
- for (int i = alleles.length - 1; i >= 0; i--)
+ for (int i = allele.length() - 1; i >= 0; i--)
{
- complement.append(Dna.getComplement(alleles[i]));
+ complement.append(Dna.getComplement(allele.charAt(i)));
}
}
}
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.print.PrinterJob;
import java.beans.PropertyChangeEvent;
import java.io.File;
+import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
{
formatMenu.add(vsel);
}
+ addFocusListener(new FocusAdapter()
+ {
+ @Override
+ public void focusGained(FocusEvent e)
+ {
+ Desktop.setCurrentAlignFrame(AlignFrame.this);
+ }
+ });
}
.setSelected(av.getGlobalColourScheme() instanceof jalview.schemes.RNAHelicesColour);
showProducts.setEnabled(canShowProducts());
+ setGroovyEnabled(Desktop.getGroovyConsole() != null);
updateEditMenuBar();
}
+ /**
+ * Set the enabled state of the 'Run Groovy' option in the Calculate menu
+ *
+ * @param b
+ */
+ public void setGroovyEnabled(boolean b)
+ {
+ runGroovy.setEnabled(b);
+ }
+
private IProgressIndicator progressBar;
/*
@Override
public void mousePressed(MouseEvent evt)
{
- if (evt.isControlDown()
- || SwingUtilities.isRightMouseButton(evt))
+ if (evt.isPopupTrigger())
{
radioItem.removeActionListener(radioItem.getActionListeners()[0]);
{
JMenuItem tm = new JMenuItem();
ScoreModelI sm = ResidueProperties.scoreMatrices.get(pwtype);
- if (sm.isProtein() == !viewport.getAlignment().isNucleotide())
+ if (sm.isDNA() == viewport.getAlignment().isNucleotide()
+ || sm.isProtein() == !viewport.getAlignment()
+ .isNucleotide())
{
String smn = MessageManager.getStringOrReturn(
"label.score_model_", sm.getName());
@Override
public void tabbedPane_mousePressed(MouseEvent e)
{
- if (SwingUtilities.isRightMouseButton(e))
+ if (e.isPopupTrigger())
{
String msg = MessageManager.getString("label.enter_view_name");
String reply = JOptionPane.showInternalInputDialog(this, msg, msg,
return;
}
}
+
+ /**
+ * Try to run a script in the Groovy console, having first ensured that this
+ * AlignFrame is set as currentAlignFrame in Desktop, to allow the script to
+ * be targeted at this alignment.
+ */
+ @Override
+ protected void runGroovy_actionPerformed()
+ {
+ Desktop.setCurrentAlignFrame(this);
+ Object console = Desktop.instance.getGroovyConsole();
+ if (console != null)
+ {
+ /*
+ * use reflection here to avoid compile-time dependency
+ * on Groovy libraries
+ */
+ try
+ {
+ Class<?> gcClass = getClass().getClassLoader().loadClass(
+ "groovy.ui.Console");
+ Method runScript = gcClass.getMethod("runScript");
+ runScript.invoke(console);
+ } catch (Exception ex)
+ {
+ System.err.println((ex.toString()));
+ JOptionPane
+ .showInternalMessageDialog(Desktop.desktop, MessageManager
+ .getString("label.couldnt_run_groovy_script"),
+ MessageManager
+ .getString("label.groovy_support_failed"),
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ else
+ {
+ System.err.println("Can't run Groovy script as console not found");
+ }
+ }
}
class PrintThread extends Thread
}
}
}
- if (!SwingUtilities.isRightMouseButton(evt))
+ if (!evt.isPopupTrigger())
{
return;
}
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.Scrollable;
-import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
/**
}
}
- if (SwingUtilities.isRightMouseButton(evt) && activeRow != -1)
+ if (evt.isPopupTrigger() && activeRow != -1)
{
if (av.getColumnSelection() == null)
{
});
SwingUtilities.invokeLater(new Runnable()
{
+ @Override
public void run()
{
textarea.requestFocus();
textarea.setText(text);
}
+ @Override
public void save_actionPerformed(ActionEvent e)
{
JalviewFileChooser chooser = new JalviewFileChooser(
}
}
+ @Override
public void toggleHtml_actionPerformed(ActionEvent e)
{
String txt = textarea.getText();
* @param e
* DOCUMENT ME!
*/
+ @Override
public void copyItem_actionPerformed(ActionEvent e)
{
Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
* @param e
* DOCUMENT ME!
*/
+ @Override
public void cancel_actionPerformed(ActionEvent e)
{
try
}
}
+ @Override
public void textarea_mousePressed(MouseEvent e)
{
- if (SwingUtilities.isRightMouseButton(e))
+ if (e.isPopupTrigger())
{
JPopupMenu popup = new JPopupMenu(
MessageManager.getString("action.edit"));
MessageManager.getString("action.copy"));
item.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
copyItem_actionPerformed(e);
@Override
public void textarea_mousePressed(MouseEvent e)
{
- if (SwingUtilities.isRightMouseButton(e))
+ if (e.isPopupTrigger())
{
JPopupMenu popup = new JPopupMenu(
MessageManager.getString("action.edit"));
ListSelectionModel rowSM = table.getSelectionModel();
rowSM.addListSelectionListener(new ListSelectionListener()
{
+ @Override
public void valueChanged(ListSelectionEvent e)
{
ListSelectionModel lsm = (ListSelectionModel) e.getSource();
table.addMouseListener(new MouseAdapter()
{
+ @Override
public void mouseClicked(MouseEvent evt)
{
- if (evt.getClickCount() == 2
- || SwingUtilities.isRightMouseButton(evt))
+ if (evt.getClickCount() == 2 || evt.isPopupTrigger())
{
editRemoveLocalSource(evt);
}
this(null);
}
+ @Override
public void paintComponent(java.awt.Graphics g)
{
if (sourceRegistry == null)
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
+ @Override
public void run()
{
TableSorter sorter = (TableSorter) table.getModel();
fullDetails.setText(text.toString());
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
+ @Override
public void run()
{
fullDetailsScrollpane.getVerticalScrollBar().setValue(0);
});
}
+ @Override
public void run()
{
loadingDasSources = true;
return selected;
}
+ @Override
public void refresh_actionPerformed(ActionEvent e)
{
saveProperties(jalview.bin.Cache.applicationProperties);
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
+ @Override
public void run()
{
filter1.setSelectedIndex(0);
});
}
+ @Override
public void amendLocal(boolean newSource)
{
String url = "http://localhost:8080/", nickname = "";
SwingUtilities.invokeLater(new Runnable()
{
+ @Override
public void run()
{
scrollPane.getVerticalScrollBar().setValue(
refreshTableData(data);
SwingUtilities.invokeLater(new Runnable()
{
+ @Override
public void run()
{
scrollPane.getVerticalScrollBar().setValue(
}
}
+ @Override
public void valueChanged(ListSelectionEvent evt)
{
// Called when the MainTable selection changes
}
}
+ @Override
public void reset_actionPerformed(ActionEvent e)
{
registryURL.setText(sourceRegistry.getDasRegistryURL());
private Object[][] data;
+ @Override
public int getColumnCount()
{
return columnNames.length;
}
+ @Override
public int getRowCount()
{
return data.length;
}
+ @Override
public String getColumnName(int col)
{
return columnNames[col];
}
+ @Override
public Object getValueAt(int row, int col)
{
return data[row][col];
* each cell. If we didn't implement this method, then the last column would
* contain text ("true"/"false"), rather than a check box.
*/
+ @Override
public Class getColumnClass(int c)
{
return getValueAt(0, c).getClass();
/*
* Don't need to implement this method unless your table's editable.
*/
+ @Override
public boolean isCellEditable(int row, int col)
{
// Note that the data/cell address is constant,
/*
* Don't need to implement this method unless your table's data can change.
*/
+ @Override
public void setValueAt(Object value, int row, int col)
{
data[row][col] = value;
Thread thr = new Thread(new Runnable()
{
+ @Override
public void run()
{
// this actually initialises the das source list
@Override
public void mousePressed(MouseEvent evt)
{
- if (SwingUtilities.isRightMouseButton(evt))
+ if (evt.isPopupTrigger())
{
showPasteMenu(evt.getX(), evt.getY());
}
java.lang.reflect.Method setvar = gcClass.getMethod("setVariable",
new Class[] { String.class, Object.class });
java.lang.reflect.Method run = gcClass.getMethod("run");
- Object gc = gccons.newInstance();
- setvar.invoke(gc, new Object[] { "Jalview", this });
- run.invoke(gc);
+ groovyConsole = gccons.newInstance();
+ setvar.invoke(groovyConsole, new Object[] { "Jalview", this });
+ run.invoke(groovyConsole);
+ /*
+ * and rebuild alignframe menus to enable 'Run Groovy'
+ */
+
+ AlignFrame[] alignFrames = getAlignFrames();
+ if (alignFrames != null)
+ {
+ for (AlignFrame af : alignFrames)
+ {
+ af.setGroovyEnabled(true);
+ }
+ }
} catch (Exception ex)
{
jalview.bin.Cache.log.error("Groovy Shell Creation failed.", ex);
*/
private java.util.concurrent.Semaphore block = new Semaphore(0);
+ /*
+ * groovy.ui.Console object - if Groovy jars are present and the
+ * user has activated the Groovy console. Use via reflection to
+ * avoid compile-time dependency on Groovy libraries.
+ */
+ private static Object groovyConsole;
+
/**
* add another dialog thread to the queue
*
Desktop.currentAlignFrame = currentAlignFrame;
}
+ public static Object getGroovyConsole()
+ {
+ return groovyConsole;
+ }
+
}
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.Vector;
public void mousePressed(MouseEvent evt)
{
selectedRow = table.rowAtPoint(evt.getPoint());
- if (SwingUtilities.isRightMouseButton(evt))
+ if (evt.isPopupTrigger())
{
popupSort(selectedRow, (String) table.getValueAt(selectedRow, 0),
table.getValueAt(selectedRow, 1), fr.getMinMax(),
}
protected void popupSort(final int selectedRow, final String type,
- final Object typeCol, final Hashtable minmax, int x, int y)
+ final Object typeCol, final Map<String, float[][]> minmax, int x,
+ int y)
{
JPopupMenu men = new JPopupMenu(MessageManager.formatMessage(
"label.settings_for_param", new String[] { type }));
men.add(dens);
if (minmax != null)
{
- final Object typeMinMax = minmax.get(type);
+ final float[][] typeMinMax = minmax.get(type);
/*
* final JCheckBoxMenuItem chb = new JCheckBoxMenuItem("Vary Height"); //
* this is broken at the moment and isn't that useful anyway!
*
* men.add(chb);
*/
- if (typeMinMax != null && ((float[][]) typeMinMax)[0] != null)
+ if (typeMinMax != null && typeMinMax[0] != null)
{
// if (table.getValueAt(row, column));
// graduated colourschemes for those where minmax exists for the
* Ignore single click. Ignore 'left' click followed by 'right' click (user
* selects a row then its pop-up menu).
*/
- if (e.getClickCount() < 2 || SwingUtilities.isRightMouseButton(e))
+ if (e.getClickCount() < 2 || e.isPopupTrigger())
{
return;
}
int seq = alignPanel.getSeqPanel().findSeq(e);
- if (SwingUtilities.isRightMouseButton(e))
+ if (e.isPopupTrigger())
{
Sequence sq = (Sequence) av.getAlignment().getSequenceAt(seq);
// build a new links menu based on the current links + any non-positional
// features
- Vector nlinks = new Vector(Preferences.sequenceURLLinks);
- SequenceFeature sf[] = sq == null ? null : sq.getSequenceFeatures();
- for (int sl = 0; sf != null && sl < sf.length; sl++)
+ Vector<String> nlinks = new Vector<String>(
+ Preferences.sequenceURLLinks);
+ SequenceFeature sfs[] = sq == null ? null : sq.getSequenceFeatures();
+ if (sfs != null)
{
- if (sf[sl].begin == sf[sl].end && sf[sl].begin == 0)
+ for (SequenceFeature sf : sfs)
{
- if (sf[sl].links != null && sf[sl].links.size() > 0)
+ if (sf.begin == sf.end && sf.begin == 0)
{
- for (int l = 0, lSize = sf[sl].links.size(); l < lSize; l++)
+ if (sf.links != null && sf.links.size() > 0)
{
- nlinks.addElement(sf[sl].links.elementAt(l));
+ for (int l = 0, lSize = sf.links.size(); l < lSize; l++)
+ {
+ nlinks.addElement(sf.links.elementAt(l));
+ }
}
}
}
}
- jalview.gui.PopupMenu pop = new jalview.gui.PopupMenu(alignPanel, sq,
- nlinks, new Vector(Preferences.getGroupURLLinks()));
+ PopupMenu pop = new PopupMenu(alignPanel, sq, nlinks,
+ Preferences.getGroupURLLinks());
pop.show(this, e.getX(), e.getY());
return;
add(enabled, BorderLayout.NORTH);
for (Object str : opt.getPossibleValues())
{
- val.addItem((String) str);
+ val.addItem(str);
}
- val.setSelectedItem((String) opt.getValue());
+ val.setSelectedItem(opt.getValue());
if (opt.getPossibleValues().size() > 1)
{
setLayout(new GridLayout(1, 2));
setInitialValue();
}
+ @Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() != enabled)
return opt;
}
+ @Override
public void mouseClicked(MouseEvent e)
{
- if (javax.swing.SwingUtilities.isRightMouseButton(e))
+ if (e.isPopupTrigger())
{
showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
}
}
+ @Override
public void mouseEntered(MouseEvent e)
{
// TODO Auto-generated method stub
}
+ @Override
public void mouseExited(MouseEvent e)
{
// TODO Auto-generated method stub
}
+ @Override
public void mousePressed(MouseEvent e)
{
// TODO Auto-generated method stub
}
+ @Override
public void mouseReleased(MouseEvent e)
{
// TODO Auto-generated method stub
showDesc.addActionListener(new ActionListener()
{
+ @Override
public void actionPerformed(ActionEvent e)
{
descisvisible = !descisvisible;
validate();
}
+ @Override
public void actionPerformed(ActionEvent e)
{
if (adjusting)
lastVal = null;
}
+ @Override
public void mouseClicked(MouseEvent e)
{
- if (javax.swing.SwingUtilities.isRightMouseButton(e))
+ if (e.isPopupTrigger())
{
showUrlPopUp(this, finfo.toString(), e.getX(), e.getY());
}
}
+ @Override
public void mouseEntered(MouseEvent e)
{
// TODO Auto-generated method stub
}
+ @Override
public void mouseExited(MouseEvent e)
{
// TODO Auto-generated method stub
}
+ @Override
public void mousePressed(MouseEvent e)
{
// TODO Auto-generated method stub
}
+ @Override
public void mouseReleased(MouseEvent e)
{
// TODO Auto-generated method stub
}
+ @Override
public void stateChanged(ChangeEvent e)
{
if (!adjusting)
{
valueField.setText(""
- + ((integ) ? ("" + (int) slider.getValue())
- : ("" + (float) (slider.getValue() / 1000f))));
+ + ((integ) ? ("" + slider.getValue())
+ : ("" + slider.getValue() / 1000f)));
checkIfModified();
}
import jalview.analysis.AlignmentAnnotationUtils;
import jalview.analysis.AlignmentUtils;
import jalview.analysis.Conservation;
+import jalview.bin.Cache;
import jalview.commands.ChangeCaseCommand;
import jalview.commands.EditCommand;
import jalview.commands.EditCommand.Action;
import jalview.schemes.TurnColourScheme;
import jalview.schemes.UserColourScheme;
import jalview.schemes.ZappoColourScheme;
+import jalview.util.DBRefUtils;
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.Collections;
import java.util.Hashtable;
{
private static final String ALL_ANNOTATIONS = "All";
- private static final String COMMA = ",";
-
JMenu groupMenu = new JMenu();
JMenuItem groupName = new JMenuItem();
* @param seq
* DOCUMENT ME!
*/
- public PopupMenu(final AlignmentPanel ap, Sequence seq, Vector links)
+ public PopupMenu(final AlignmentPanel ap, Sequence seq, List<String> links)
{
this(ap, seq, links, null);
}
* @param groupLinks
*/
public PopupMenu(final AlignmentPanel ap, final SequenceI seq,
- Vector links, Vector groupLinks)
+ List<String> links, List<String> groupLinks)
{
// /////////////////////////////////////////////////////////
// If this is activated from the sequence panel, the user may want to
if (links != null && links.size() > 0)
{
+ addFeatureLinks(seq, links);
+ }
+ }
- JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));
- Vector linkset = new Vector();
- for (int i = 0; i < links.size(); i++)
+ /**
+ * Adds a 'Link' menu item with a sub-menu item for each hyperlink provided.
+ *
+ * @param seq
+ * @param links
+ */
+ void addFeatureLinks(final SequenceI seq, List<String> links)
+ {
+ JMenu linkMenu = new JMenu(MessageManager.getString("action.link"));
+ List<String> linkset = new ArrayList<String>();
+ for (String link : links)
+ {
+ UrlLink urlLink = null;
+ try
{
- String link = links.elementAt(i).toString();
- UrlLink urlLink = null;
- try
- {
- urlLink = new UrlLink(link);
- } catch (Exception foo)
- {
- jalview.bin.Cache.log.error("Exception for URLLink '" + link
- + "'", foo);
- continue;
- }
- ;
- if (!urlLink.isValid())
+ urlLink = new UrlLink(link);
+ } catch (Exception foo)
+ {
+ Cache.log.error("Exception for URLLink '" + link + "'", foo);
+ continue;
+ }
+ ;
+ if (!urlLink.isValid())
+ {
+ Cache.log.error(urlLink.getInvalidMessage());
+ continue;
+ }
+ final String label = urlLink.getLabel();
+ if (seq != null && urlLink.isDynamic())
+ {
+
+ // collect matching db-refs
+ DBRefEntry[] dbr = DBRefUtils.selectRefs(seq.getDBRefs(),
+ new String[] { urlLink.getTarget() });
+ // collect id string too
+ String id = seq.getName();
+ String descr = seq.getDescription();
+ if (descr != null && descr.length() < 1)
{
- jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
- continue;
+ descr = null;
}
- final String label = urlLink.getLabel();
- if (seq != null && urlLink.isDynamic())
- {
- // collect matching db-refs
- DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(
- seq.getDBRefs(), new String[] { urlLink.getTarget() });
- // collect id string too
- String id = seq.getName();
- String descr = seq.getDescription();
- if (descr != null && descr.length() < 1)
- {
- descr = null;
- }
-
- if (dbr != null)
+ if (dbr != null)
+ {
+ for (int r = 0; r < dbr.length; r++)
{
- for (int r = 0; r < dbr.length; r++)
+ if (id != null && dbr[r].getAccessionId().equals(id))
{
- if (id != null && dbr[r].getAccessionId().equals(id))
- {
- // suppress duplicate link creation for the bare sequence ID
- // string with this link
- id = null;
- }
- // create Bare ID link for this RUL
- String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(),
- true);
- if (urls != null)
- {
- for (int u = 0; u < urls.length; u += 2)
- {
- if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
- {
- linkset.addElement(urls[u] + "|" + urls[u + 1]);
- addshowLink(linkMenu, label + "|" + urls[u],
- urls[u + 1]);
- }
- }
- }
+ // suppress duplicate link creation for the bare sequence ID
+ // string with this link
+ id = null;
}
- }
- if (id != null)
- {
- // create Bare ID link for this RUL
- String[] urls = urlLink.makeUrls(id, true);
+ // create Bare ID link for this URL
+ String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(), true);
if (urls != null)
{
for (int u = 0; u < urls.length; u += 2)
{
if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
{
- linkset.addElement(urls[u] + "|" + urls[u + 1]);
- addshowLink(linkMenu, label, urls[u + 1]);
+ linkset.add(urls[u] + "|" + urls[u + 1]);
+ addshowLink(linkMenu, label + "|" + urls[u], urls[u + 1]);
}
}
}
}
- // Create urls from description but only for URL links which are regex
- // links
- if (descr != null && urlLink.getRegexReplace() != null)
+ }
+ if (id != null)
+ {
+ // create Bare ID link for this URL
+ String[] urls = urlLink.makeUrls(id, true);
+ if (urls != null)
{
- // create link for this URL from description where regex matches
- String[] urls = urlLink.makeUrls(descr, true);
- if (urls != null)
+ for (int u = 0; u < urls.length; u += 2)
{
- for (int u = 0; u < urls.length; u += 2)
+ if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
{
- if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
- {
- linkset.addElement(urls[u] + "|" + urls[u + 1]);
- addshowLink(linkMenu, label, urls[u + 1]);
- }
+ linkset.add(urls[u] + "|" + urls[u + 1]);
+ addshowLink(linkMenu, label, urls[u + 1]);
}
}
}
}
- else
+ // Create urls from description but only for URL links which are regex
+ // links
+ if (descr != null && urlLink.getRegexReplace() != null)
{
- if (!linkset.contains(label + "|" + urlLink.getUrl_prefix()))
+ // create link for this URL from description where regex matches
+ String[] urls = urlLink.makeUrls(descr, true);
+ if (urls != null)
{
- linkset.addElement(label + "|" + urlLink.getUrl_prefix());
- // Add a non-dynamic link
- addshowLink(linkMenu, label, urlLink.getUrl_prefix());
+ for (int u = 0; u < urls.length; u += 2)
+ {
+ if (!linkset.contains(urls[u] + "|" + urls[u + 1]))
+ {
+ linkset.add(urls[u] + "|" + urls[u + 1]);
+ addshowLink(linkMenu, label, urls[u + 1]);
+ }
+ }
}
}
}
- if (sequence != null)
- {
- sequenceMenu.add(linkMenu);
- }
else
{
- add(linkMenu);
+ if (!linkset.contains(label + "|" + urlLink.getUrl_prefix()))
+ {
+ linkset.add(label + "|" + urlLink.getUrl_prefix());
+ // Add a non-dynamic link
+ addshowLink(linkMenu, label, urlLink.getUrl_prefix());
+ }
}
}
+ if (sequence != null)
+ {
+ sequenceMenu.add(linkMenu);
+ }
+ else
+ {
+ add(linkMenu);
+ }
}
/**
showOrHideMenu.add(item);
}
- private void buildGroupURLMenu(SequenceGroup sg, Vector groupLinks)
+ private void buildGroupURLMenu(SequenceGroup sg, List<String> groupLinks)
{
// TODO: usability: thread off the generation of group url content so root
// ID/regex match URLs
groupLinksMenu = new JMenu(
MessageManager.getString("action.group_link"));
+ // three types of url that might be created.
JMenu[] linkMenus = new JMenu[] { null,
new JMenu(MessageManager.getString("action.ids")),
new JMenu(MessageManager.getString("action.sequences")),
- new JMenu(MessageManager.getString("action.ids_sequences")) }; // three
- // types
- // of url
- // that
- // might
- // be
- // created.
+ new JMenu(MessageManager.getString("action.ids_sequences")) };
+
SequenceI[] seqs = ap.av.getSelectionAsNewSequence();
String[][] idandseqs = GroupUrlLink.formStrings(seqs);
- Hashtable commonDbrefs = new Hashtable();
+ Hashtable<String, Object[]> commonDbrefs = new Hashtable<String, Object[]>();
for (int sq = 0; sq < seqs.length; sq++)
{
for (int d = 0; d < dbr.length; d++)
{
String src = dbr[d].getSource(); // jalview.util.DBRefUtils.getCanonicalName(dbr[d].getSource()).toUpperCase();
- Object[] sarray = (Object[]) commonDbrefs.get(src);
+ Object[] sarray = commonDbrefs.get(src);
if (sarray == null)
{
sarray = new Object[2];
// now create group links for all distinct ID/sequence sets.
boolean addMenu = false; // indicates if there are any group links to give
// to user
- for (int i = 0; i < groupLinks.size(); i++)
+ for (String link : groupLinks)
{
- String link = groupLinks.elementAt(i).toString();
GroupUrlLink urlLink = null;
try
{
urlLink = new GroupUrlLink(link);
} catch (Exception foo)
{
- jalview.bin.Cache.log.error("Exception for GroupURLLink '" + link
+ Cache.log.error("Exception for GroupURLLink '" + link
+ "'", foo);
continue;
}
;
if (!urlLink.isValid())
{
- jalview.bin.Cache.log.error(urlLink.getInvalidMessage());
+ Cache.log.error(urlLink.getInvalidMessage());
continue;
}
final String label = urlLink.getLabel();
boolean usingNames = false;
// Now see which parts of the group apply for this URL
String ltarget = urlLink.getTarget(); // jalview.util.DBRefUtils.getCanonicalName(urlLink.getTarget());
- Object[] idset = (Object[]) commonDbrefs.get(ltarget.toUpperCase());
+ Object[] idset = commonDbrefs.get(ltarget.toUpperCase());
String[] seqstr, ids; // input to makeUrl
if (idset != null)
{
new Object[] { urlgenerator.getUrl_prefix(),
urlgenerator.getNumberInvolved(urlstub) }));
// TODO: put in info about what is being sent.
- item.addActionListener(new java.awt.event.ActionListener()
+ item.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
try
{
showLink(urlgenerator.constructFrom(urlstub));
- } catch (UrlStringTooLongException e)
+ } catch (UrlStringTooLongException e2)
{
}
}
import jalview.jbgui.GSequenceLink;
import jalview.schemes.ColourSchemeProperty;
import jalview.util.MessageManager;
+import jalview.util.Platform;
import jalview.ws.sifts.SiftsSettings;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.io.File;
-import java.util.Collection;
+import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
* Holds name and link separated with | character. Sequence ID must be
* $SEQUENCE_ID$ or $SEQUENCE_ID=/.possible | chars ./=$
*/
- public static Vector sequenceURLLinks;
+ public static Vector<String> sequenceURLLinks;
/**
* Holds name and link separated with | character. Sequence IDS and Sequences
* (TODO: proper escape for using | to separate ids or sequences
*/
- public static Vector groupURLLinks;
+ public static List<String> groupURLLinks;
static
{
String string = Cache
.getDefault(
"SEQUENCE_LINKS",
"EMBL-EBI Search|http://www.ebi.ac.uk/ebisearch/search.ebi?db=allebi&query=$SEQUENCE_ID$");
- sequenceURLLinks = new Vector();
+ sequenceURLLinks = new Vector<String>();
try
{
* .properties file as '|' separated strings
*/
- groupURLLinks = new Vector();
+ groupURLLinks = new ArrayList<String>();
}
- Vector nameLinks, urlLinks;
+ Vector<String> nameLinks, urlLinks;
JInternalFrame frame;
wsPrefs = new WsPreferences();
wsTab.add(wsPrefs, BorderLayout.CENTER);
int width = 500, height = 450;
- if (new jalview.util.Platform().isAMac())
+ new jalview.util.Platform();
+ if (Platform.isAMac())
{
width = 570;
height = 480;
/*
* Set Connections tab defaults
*/
- nameLinks = new Vector();
- urlLinks = new Vector();
+ nameLinks = new Vector<String>();
+ urlLinks = new Vector<String>();
for (int i = 0; i < sequenceURLLinks.size(); i++)
{
String link = sequenceURLLinks.elementAt(i).toString();
if (nameLinks.size() > 0)
{
StringBuffer links = new StringBuffer();
- sequenceURLLinks = new Vector();
+ sequenceURLLinks = new Vector<String>();
for (int i = 0; i < nameLinks.size(); i++)
{
sequenceURLLinks.addElement(nameLinks.elementAt(i) + "|"
super.showunconserved_actionPerformed(e);
}
- public static Collection getGroupURLLinks()
+ public static List<String> getGroupURLLinks()
{
return groupURLLinks;
}
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
-import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
/**
min = res;
max = res;
- if (SwingUtilities.isRightMouseButton(evt))
+ if (evt.isPopupTrigger())
{
rightMouseButtonPressed(evt, res);
}
package jalview.gui;
import jalview.api.AlignViewportI;
+import jalview.bin.Cache;
import jalview.commands.EditCommand;
import jalview.commands.EditCommand.Action;
import jalview.commands.EditCommand.Edit;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
+import java.util.ArrayList;
import java.util.List;
-import java.util.Vector;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
/**
void insertNucAtCursor(boolean group, String nuc)
{
+ // TODO not called - delete?
groupEditing = group;
startseq = seqCanvas.cursorY;
lastres = seqCanvas.cursorX;
{
lastMousePress = evt.getPoint();
- if (javax.swing.SwingUtilities.isMiddleMouseButton(evt))
+ if (SwingUtilities.isMiddleMouseButton(evt))
{
mouseWheelPressed = true;
return;
{
for (int j = 0; j < startres - lastres; j++)
{
- if (!jalview.util.Comparison.isGap(groupSeqs[g]
- .getCharAt(fixedRight - j)))
+ if (!Comparison.isGap(groupSeqs[g].getCharAt(fixedRight - j)))
{
blank = false;
break;
continue;
}
- if (!jalview.util.Comparison.isGap(groupSeqs[g].getCharAt(j)))
+ if (!Comparison.isGap(groupSeqs[g].getCharAt(j)))
{
// Not a gap, block edit not valid
endEditing();
for (blankColumn = fixedColumn; blankColumn > j; blankColumn--)
{
- if (jalview.util.Comparison.isGap(seq[s].getCharAt(blankColumn)))
+ if (Comparison.isGap(seq[s].getCharAt(blankColumn)))
{
// Theres a space, so break and insert the gap
break;
}
- if (javax.swing.SwingUtilities.isRightMouseButton(evt))
+ if (evt.isPopupTrigger())
{
List<SequenceFeature> allFeatures = ap.getFeatureRenderer()
.findFeaturesAtRes(sequence.getDatasetSequence(),
sequence.findPosition(res));
- Vector links = new Vector();
+ List<String> links = new ArrayList<String>();
for (SequenceFeature sf : allFeatures)
{
if (sf.links != null)
{
- for (int j = 0; j < sf.links.size(); j++)
+ for (String link : sf.links)
{
- links.addElement(sf.links.elementAt(j));
+ links.add(link);
}
}
}
- jalview.gui.PopupMenu pop = new jalview.gui.PopupMenu(ap, null, links);
+ PopupMenu pop = new PopupMenu(ap, null, links);
pop.show(this, evt.getX(), evt.getY());
return;
}
{
if (av.getAlignment() == null)
{
- jalview.bin.Cache.log.warn("alignviewport av SeqSetId="
+ Cache.log.warn("alignviewport av SeqSetId="
+ av.getSequenceSetId() + " ViewId=" + av.getViewId()
+ " 's alignment is NULL! returning immediately.");
return;
import javax.swing.JColorChooser;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
-import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
/**
{
if (highlightNode != null)
{
- if (SwingUtilities.isRightMouseButton(evt))
+ if (evt.isPopupTrigger())
{
Color col = JColorChooser.showDialog(this,
MessageManager.getString("label.select_subtree_colour"),
}
else if (format.equals(IdentifyFile.FeaturesFile))
{
- alignFile = new FeaturesFile(inFile, type);
+ alignFile = new FeaturesFile(true, inFile, type);
}
return buildAlignmentFrom(alignFile);
} catch (Exception e)
import jalview.datamodel.DBRefEntry;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
+import jalview.io.gff.GffConstants;
+import jalview.util.DBRefUtils;
import jalview.util.UrlLink;
import java.util.ArrayList;
-import java.util.Hashtable;
import java.util.List;
+import java.util.Map;
/**
* generate HTML reports for a sequence
}
/**
- * appends the features at rpos to the given stringbuffer ready for display in
- * a tooltip
+ * Append text for the list of features to the tooltip
*
* @param tooltipText2
- * @param linkImageURL
* @param rpos
* @param features
- * TODO refactor to Jalview 'utilities' somehow.
+ * @param minmax
*/
public void appendFeatures(final StringBuffer tooltipText2, int rpos,
- List<SequenceFeature> features)
+ List<SequenceFeature> features, Map<String, float[][]> minmax)
{
- appendFeatures(tooltipText2, rpos, features, null);
+ if (features != null)
+ {
+ for (SequenceFeature feature : features)
+ {
+ appendFeature(tooltipText2, rpos, minmax, feature);
+ }
+ }
}
- public void appendFeatures(final StringBuffer tooltipText2, int rpos,
- List<SequenceFeature> features, Hashtable minmax)
+ /**
+ * Appends text for one sequence feature to the string buffer
+ *
+ * @param sb
+ * @param rpos
+ * @param minmax
+ * {{min, max}, {min, max}} positional and non-positional feature
+ * scores for this type
+ * @param feature
+ */
+ void appendFeature(final StringBuffer sb, int rpos,
+ Map<String, float[][]> minmax, SequenceFeature feature)
{
- String tmpString;
- if (features != null)
+ if ("disulfide bond".equals(feature.getType()))
{
- for (SequenceFeature feature : features)
+ if (feature.getBegin() == rpos || feature.getEnd() == rpos)
{
- if (feature.getType().equals("disulfide bond"))
+ if (sb.length() > 6)
{
- if (feature.getBegin() == rpos || feature.getEnd() == rpos)
- {
- if (tooltipText2.length() > 6)
- {
- tooltipText2.append("<br>");
- }
- tooltipText2.append("disulfide bond " + feature.getBegin()
- + ":" + feature.getEnd());
- }
+ sb.append("<br>");
}
- else
+ sb.append("disulfide bond ").append(feature.getBegin()).append(":")
+ .append(feature.getEnd());
+ }
+ }
+ else
+ {
+ if (sb.length() > 6)
+ {
+ sb.append("<br>");
+ }
+ // TODO: remove this hack to display link only features
+ boolean linkOnly = feature.getValue("linkonly") != null;
+ if (!linkOnly)
+ {
+ sb.append(feature.getType()).append(" ");
+ if (rpos != 0)
{
- if (tooltipText2.length() > 6)
+ // we are marking a positional feature
+ sb.append(feature.begin);
+ }
+ if (feature.begin != feature.end)
+ {
+ sb.append(" " + feature.end);
+ }
+
+ if (feature.getDescription() != null
+ && !feature.description.equals(feature.getType()))
+ {
+ String tmpString = feature.getDescription();
+ String tmp2up = tmpString.toUpperCase();
+ final int startTag = tmp2up.indexOf("<HTML>");
+ if (startTag > -1)
{
- tooltipText2.append("<br>");
+ tmpString = tmpString.substring(startTag + 6);
+ tmp2up = tmp2up.substring(startTag + 6);
}
- // TODO: remove this hack to display link only features
- boolean linkOnly = feature.getValue("linkonly") != null;
- if (!linkOnly)
+ // TODO strips off </body> but not <body> - is that intended?
+ int endTag = tmp2up.indexOf("</BODY>");
+ if (endTag > -1)
{
- tooltipText2.append(feature.getType() + " ");
- if (rpos != 0)
- {
- // we are marking a positional feature
- tooltipText2.append(feature.begin);
- }
- if (feature.begin != feature.end)
- {
- tooltipText2.append(" " + feature.end);
- }
-
- if (feature.getDescription() != null
- && !feature.description.equals(feature.getType()))
- {
- tmpString = feature.getDescription();
- String tmp2up = tmpString.toUpperCase();
- int startTag = tmp2up.indexOf("<HTML>");
- if (startTag > -1)
- {
- tmpString = tmpString.substring(startTag + 6);
- tmp2up = tmp2up.substring(startTag + 6);
- }
- int endTag = tmp2up.indexOf("</BODY>");
- if (endTag > -1)
- {
- tmpString = tmpString.substring(0, endTag);
- tmp2up = tmp2up.substring(0, endTag);
- }
- endTag = tmp2up.indexOf("</HTML>");
- if (endTag > -1)
- {
- tmpString = tmpString.substring(0, endTag);
- }
-
- if (startTag > -1)
- {
- tooltipText2.append("; " + tmpString);
- }
- else
- {
- if (tmpString.indexOf("<") > -1
- || tmpString.indexOf(">") > -1)
- {
- // The description does not specify html is to
- // be used, so we must remove < > symbols
- tmpString = tmpString.replaceAll("<", "<");
- tmpString = tmpString.replaceAll(">", ">");
-
- tooltipText2.append("; ");
- tooltipText2.append(tmpString);
+ tmpString = tmpString.substring(0, endTag);
+ tmp2up = tmp2up.substring(0, endTag);
+ }
+ endTag = tmp2up.indexOf("</HTML>");
+ if (endTag > -1)
+ {
+ tmpString = tmpString.substring(0, endTag);
+ }
- }
- else
- {
- tooltipText2.append("; " + tmpString);
- }
- }
- }
- // check score should be shown
- if (!Float.isNaN(feature.getScore()))
+ if (startTag > -1)
+ {
+ sb.append("; ").append(tmpString);
+ }
+ else
+ {
+ if (tmpString.indexOf("<") > -1
+ || tmpString.indexOf(">") > -1)
{
- float[][] rng = (minmax == null) ? null : ((float[][]) minmax
- .get(feature.getType()));
- if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
- {
- tooltipText2.append(" Score=" + feature.getScore());
- }
+ // The description does not specify html is to
+ // be used, so we must remove < > symbols
+ tmpString = tmpString.replaceAll("<", "<");
+ tmpString = tmpString.replaceAll(">", ">");
+ sb.append("; ").append(tmpString);
}
- if (feature.getValue("status") != null)
+ else
{
- String status = feature.getValue("status").toString();
- if (status.length() > 0)
- {
- tooltipText2.append("; (" + feature.getValue("status")
- + ")");
- }
+ sb.append("; ").append(tmpString);
}
}
}
- if (feature.links != null)
+
+ /*
+ * score should be shown if there is one, and min != max
+ * for this feature type (e.g. not all 0)
+ */
+ if (!Float.isNaN(feature.getScore()))
{
- if (linkImageURL != null)
+ float[][] rng = (minmax == null) ? null : minmax.get(feature
+ .getType());
+ if (rng != null && rng[0] != null && rng[0][0] != rng[0][1])
{
- tooltipText2.append(" <img src=\"" + linkImageURL + "\">");
+ sb.append(" Score=").append(
+ String.valueOf(feature.getScore()));
}
- else
+ }
+ String status = (String) feature.getValue("status");
+ if (status != null && status.length() > 0)
+ {
+ sb.append("; (").append(status).append(")");
+ }
+ String clinSig = (String) feature
+ .getValue(GffConstants.CLINICAL_SIGNIFICANCE);
+ if (clinSig != null)
+ {
+ sb.append("; ").append(clinSig);
+ }
+ }
+ }
+ appendLinks(sb, feature);
+ }
+
+ /**
+ * Format and appends any hyperlinks for the sequence feature to the string
+ * buffer
+ *
+ * @param sb
+ * @param feature
+ */
+ void appendLinks(final StringBuffer sb, SequenceFeature feature)
+ {
+ if (feature.links != null)
+ {
+ if (linkImageURL != null)
+ {
+ sb.append(" <img src=\"" + linkImageURL + "\">");
+ }
+ else
+ {
+ for (String urlstring : feature.links)
+ {
+ try
{
- for (String urlstring : feature.links)
+ for (String[] urllink : createLinksFrom(null, urlstring))
{
- try
- {
- for (String[] urllink : createLinksFrom(null, urlstring))
- {
- tooltipText2.append("<br/> <a href=\""
- + urllink[3]
- + "\" target=\""
- + urllink[0]
- + "\">"
- + (urllink[0].toLowerCase().equals(
- urllink[1].toLowerCase()) ? urllink[0]
- : (urllink[0] + ":" + urllink[1]))
- + "</a></br>");
- }
- } catch (Exception x)
- {
- System.err.println("problem when creating links from "
- + urlstring);
- x.printStackTrace();
- }
+ sb.append("<br/> <a href=\""
+ + urllink[3]
+ + "\" target=\""
+ + urllink[0]
+ + "\">"
+ + (urllink[0].toLowerCase().equals(
+ urllink[1].toLowerCase()) ? urllink[0]
+ : (urllink[0] + ":" + urllink[1]))
+ + "</a></br>");
}
+ } catch (Exception x)
+ {
+ System.err.println("problem when creating links from "
+ + urlstring);
+ x.printStackTrace();
}
-
}
}
+
}
}
* @return String[][] { String[] { link target, link label, dynamic component
* inserted (if any), url }}
*/
- public String[][] createLinksFrom(SequenceI seq, String link)
+ String[][] createLinksFrom(SequenceI seq, String link)
{
- ArrayList<String[]> urlSets = new ArrayList<String[]>();
- ArrayList<String> uniques = new ArrayList<String>();
+ List<String[]> urlSets = new ArrayList<String[]>();
+ List<String> uniques = new ArrayList<String>();
UrlLink urlLink = new UrlLink(link);
if (!urlLink.isValid())
{
System.err.println(urlLink.getInvalidMessage());
return null;
}
- final String target = urlLink.getTarget(); // link.substring(0,
- // link.indexOf("|"));
- final String label = urlLink.getLabel();
if (seq != null && urlLink.isDynamic())
{
-
- // collect matching db-refs
- DBRefEntry[] dbr = jalview.util.DBRefUtils.selectRefs(seq.getDBRefs(),
- new String[] { target });
- // collect id string too
- String id = seq.getName();
- String descr = seq.getDescription();
- if (descr != null && descr.length() < 1)
+ urlSets.addAll(createDynamicLinks(seq, urlLink, uniques));
+ }
+ else
+ {
+ String target = urlLink.getTarget();
+ String label = urlLink.getLabel();
+ String unq = label + "|" + urlLink.getUrl_prefix();
+ if (!uniques.contains(unq))
{
- descr = null;
+ uniques.add(unq);
+ urlSets.add(new String[] { target, label, null,
+ urlLink.getUrl_prefix() });
}
- if (dbr != null)
+ }
+
+ return urlSets.toArray(new String[][] {});
+ }
+
+ /**
+ * Formats and returns a list of dynamic href links
+ *
+ * @param seq
+ * @param urlLink
+ * @param uniques
+ */
+ List<String[]> createDynamicLinks(SequenceI seq, UrlLink urlLink,
+ List<String> uniques)
+ {
+ List<String[]> result = new ArrayList<String[]>();
+ final String target = urlLink.getTarget();
+ final String label = urlLink.getLabel();
+
+ // collect matching db-refs
+ DBRefEntry[] dbr = DBRefUtils.selectRefs(seq.getDBRefs(),
+ new String[] { target });
+ // collect id string too
+ String id = seq.getName();
+ String descr = seq.getDescription();
+ if (descr != null && descr.length() < 1)
+ {
+ descr = null;
+ }
+ if (dbr != null)
+ {
+ for (int r = 0; r < dbr.length; r++)
{
- for (int r = 0; r < dbr.length; r++)
+ if (id != null && dbr[r].getAccessionId().equals(id))
{
- if (id != null && dbr[r].getAccessionId().equals(id))
- {
- // suppress duplicate link creation for the bare sequence ID
- // string with this link
- id = null;
- }
- // create Bare ID link for this RUL
- String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(), true);
- if (urls != null)
- {
- for (int u = 0; u < urls.length; u += 2)
- {
- String unq = urls[u] + "|" + urls[u + 1];
- if (!uniques.contains(unq))
- {
- urlSets.add(new String[] { target, label, urls[u],
- urls[u + 1] });
- uniques.add(unq);
- }
- }
- }
+ // suppress duplicate link creation for the bare sequence ID
+ // string with this link
+ id = null;
}
- }
- if (id != null)
- {
- // create Bare ID link for this RUL
- String[] urls = urlLink.makeUrls(id, true);
+ // create Bare ID link for this URL
+ String[] urls = urlLink.makeUrls(dbr[r].getAccessionId(), true);
if (urls != null)
{
for (int u = 0; u < urls.length; u += 2)
String unq = urls[u] + "|" + urls[u + 1];
if (!uniques.contains(unq))
{
- urlSets.add(new String[] { target, label, urls[u],
+ result.add(new String[] { target, label, urls[u],
urls[u + 1] });
uniques.add(unq);
}
}
}
}
- if (descr != null && urlLink.getRegexReplace() != null)
+ }
+ if (id != null)
+ {
+ // create Bare ID link for this URL
+ String[] urls = urlLink.makeUrls(id, true);
+ if (urls != null)
{
- // create link for this URL from description only if regex matches
- String[] urls = urlLink.makeUrls(descr, true);
- if (urls != null)
+ for (int u = 0; u < urls.length; u += 2)
{
- for (int u = 0; u < urls.length; u += 2)
+ String unq = urls[u] + "|" + urls[u + 1];
+ if (!uniques.contains(unq))
{
- String unq = urls[u] + "|" + urls[u + 1];
- if (!uniques.contains(unq))
- {
- urlSets.add(new String[] { target, label, urls[u],
- urls[u + 1] });
- uniques.add(unq);
- }
+ result.add(new String[] { target, label, urls[u],
+ urls[u + 1] });
+ uniques.add(unq);
}
}
}
-
}
- else
+ if (descr != null && urlLink.getRegexReplace() != null)
{
- String unq = label + "|" + urlLink.getUrl_prefix();
- if (!uniques.contains(unq))
+ // create link for this URL from description only if regex matches
+ String[] urls = urlLink.makeUrls(descr, true);
+ if (urls != null)
{
- uniques.add(unq);
- // Add a non-dynamic link
- urlSets.add(new String[] { target, label, null,
- urlLink.getUrl_prefix() });
+ for (int u = 0; u < urls.length; u += 2)
+ {
+ String unq = urls[u] + "|" + urls[u + 1];
+ if (!uniques.contains(unq))
+ {
+ result.add(new String[] { target, label, urls[u],
+ urls[u + 1] });
+ uniques.add(unq);
+ }
+ }
}
}
-
- return urlSets.toArray(new String[][] {});
+ return result;
}
public void createSequenceAnnotationReport(final StringBuffer tip,
SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
- Hashtable minmax)
+ Map<String, float[][]> minmax)
{
createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats,
true, minmax);
public void createSequenceAnnotationReport(final StringBuffer tip,
SequenceI sequence, boolean showDbRefs, boolean showNpFeats,
- boolean tableWrap, Hashtable minmax)
+ boolean tableWrap, Map<String, float[][]> minmax)
{
String tmp;
tip.append("<i>");
--- /dev/null
+package jalview.io.gff;
+
+/**
+ * A class to hold constants shared by creators and consumers of GFF or feature
+ * data
+ */
+public class GffConstants
+{
+ // SequenceOntology terms are to be found in SequenceOntologyI
+
+ /*
+ * clinical_significance may be an attribute of
+ * sequence_variant data from Ensembl
+ */
+ public static final String CLINICAL_SIGNIFICANCE = "clinical_significance";
+
+ /*
+ * not instantiable
+ */
+ private GffConstants()
+ {
+ }
+}
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
-import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
protected JMenu showProducts = new JMenu();
+ protected JMenuItem runGroovy = new JMenuItem();
+
protected JMenuItem rnahelicesColour = new JMenuItem();
protected JCheckBoxMenuItem autoCalculate = new JCheckBoxMenuItem();
@Override
public void mousePressed(MouseEvent evt)
{
- if (evt.isControlDown()
- || SwingUtilities.isRightMouseButton(evt))
+ if (evt.isPopupTrigger())
{
radioItem.removeActionListener(radioItem.getActionListeners()[0]);
// for show products actions see AlignFrame.canShowProducts
showProducts.setText(MessageManager.getString("label.get_cross_refs"));
+ runGroovy.setText(MessageManager.getString("label.run_groovy"));
+ runGroovy.setToolTipText(MessageManager.getString("label.run_groovy_tip"));
+ runGroovy.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ runGroovy_actionPerformed();
+ }
+ });
+
JMenuItem openFeatureSettings = new JMenuItem(
MessageManager.getString("action.feature_settings"));
openFeatureSettings.addActionListener(new ActionListener()
alignFrameMenuBar.add(colourMenu);
alignFrameMenuBar.add(calculateMenu);
alignFrameMenuBar.add(webService);
+
fileMenu.add(fetchSequence);
fileMenu.add(addSequenceMenu);
fileMenu.add(reload);
fileMenu.add(associatedData);
fileMenu.addSeparator();
fileMenu.add(closeMenuItem);
+
+ pasteMenu.add(pasteNew);
+ pasteMenu.add(pasteThis);
editMenu.add(undoMenuItem);
editMenu.add(redoMenuItem);
editMenu.add(cut);
// editMenu.addSeparator();
editMenu.add(padGapsMenuitem);
+ showMenu.add(showAllColumns);
+ showMenu.add(showAllSeqs);
+ showMenu.add(showAllhidden);
+ hideMenu.add(hideSelColumns);
+ hideMenu.add(hideSelSequences);
+ hideMenu.add(hideAllSelection);
+ hideMenu.add(hideAllButSelection);
viewMenu.add(newView);
viewMenu.add(expandViews);
viewMenu.add(gatherViews);
colourMenu.add(modifyPID);
colourMenu.add(annotationColour);
colourMenu.add(rnahelicesColour);
+
+ sort.add(sortIDMenuItem);
+ sort.add(sortLengthMenuItem);
+ sort.add(sortGroupMenuItem);
+ sort.add(sortPairwiseMenuItem);
+ sort.add(sortByTreeMenu);
calculateMenu.add(sort);
calculateMenu.add(calculateTree);
calculateMenu.addSeparator();
calculateMenu.add(autoCalculate);
calculateMenu.add(sortByTree);
calculateMenu.addSeparator();
+ calculateMenu.add(expandAlignment);
calculateMenu.add(extractScores);
+ calculateMenu.addSeparator();
+ calculateMenu.add(runGroovy);
+
webServiceNoServices = new JMenuItem(
MessageManager.getString("label.no_services"));
webService.add(webServiceNoServices);
- pasteMenu.add(pasteNew);
- pasteMenu.add(pasteThis);
- sort.add(sortIDMenuItem);
- sort.add(sortLengthMenuItem);
- sort.add(sortGroupMenuItem);
- sort.add(sortPairwiseMenuItem);
- sort.add(sortByTreeMenu);
exportImageMenu.add(htmlMenuItem);
exportImageMenu.add(epsFile);
exportImageMenu.add(createPNG);
this.getContentPane().add(statusPanel, java.awt.BorderLayout.SOUTH);
statusPanel.add(statusBar, null);
this.getContentPane().add(tabbedPane, java.awt.BorderLayout.CENTER);
- showMenu.add(showAllColumns);
- showMenu.add(showAllSeqs);
- showMenu.add(showAllhidden);
- hideMenu.add(hideSelColumns);
- hideMenu.add(hideSelSequences);
- hideMenu.add(hideAllSelection);
- hideMenu.add(hideAllButSelection);
formatMenu.add(font);
formatMenu.addSeparator();
selectMenu.add(grpsFromSelection);
selectMenu.add(deleteGroups);
selectMenu.add(annotationColumn);
- calculateMenu.add(expandAlignment);
// TODO - determine if the listenToViewSelections button is needed : see bug
// JAL-574
// selectMenu.addSeparator();
}
/**
+ * Try to run script in a Groovy console, having first ensured that this
+ * alignframe is set as currentAlignFrame in Desktop
+ */
+ protected void runGroovy_actionPerformed()
+ {
+
+ }
+ /**
* Adds the given action listener and key accelerator to the given menu item.
* Also saves in a lookup table to support lookup of action by key stroke.
*
return col == null ? null : col.brighter().brighter().brighter();
}
+ /**
+ * Returns a color between minColour and maxColour; the RGB values are in
+ * proportion to where 'value' lies between minValue and maxValue
+ *
+ * @param value
+ * @param minValue
+ * @param minColour
+ * @param maxValue
+ * @param maxColour
+ * @return
+ */
+ public static Color getGraduatedColour(float value, float minValue,
+ Color minColour, float maxValue, Color maxColour)
+ {
+ if (minValue == maxValue)
+ {
+ return minColour;
+ }
+ if (value < minValue)
+ {
+ value = minValue;
+ }
+ if (value > maxValue)
+ {
+ value = maxValue;
+ }
+
+ /*
+ * prop = proportion of the way value is from minValue to maxValue
+ */
+ float prop = (value - minValue) / (maxValue - minValue);
+ float r = minColour.getRed() + prop
+ * (maxColour.getRed() - minColour.getRed());
+ float g = minColour.getGreen() + prop
+ * (maxColour.getGreen() - minColour.getGreen());
+ float b = minColour.getBlue() + prop
+ * (maxColour.getBlue() - minColour.getBlue());
+ return new Color(r / 255, g / 255, b / 255);
+ }
}
* @param letters
* @return
*/
- public static final boolean areNucleotide(char[][] letters)
+ static final boolean areNucleotide(char[][] letters)
{
int ntCount = 0;
int aaCount = 0;
// to save a lengthy calculation
for (char c : seq)
{
- if ('a' <= c && c <= 'z')
- {
- c -= TO_UPPER_CASE;
- }
-
- if (c == 'A' || c == 'G' || c == 'C' || c == 'T' || c == 'U')
+ if (isNucleotide(c))
{
ntCount++;
}
- else if (!Comparison.isGap(c))
+ else if (!isGap(c))
{
aaCount++;
}
}
/**
+ * Answers true if the character is one of aAcCgGtTuU
+ *
+ * @param c
+ * @return
+ */
+ public static boolean isNucleotide(char c)
+ {
+ if ('a' <= c && c <= 'z')
+ {
+ c -= TO_UPPER_CASE;
+ }
+
+ switch (c)
+ {
+ case 'A':
+ case 'C':
+ case 'G':
+ case 'T':
+ case 'U':
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Answers true if every character in the string is one of aAcCgGtTuU, or
+ * (optionally) a gap character (dot, dash, space), else false
+ *
+ * @param s
+ * @param allowGaps
+ * @return
+ */
+ public static boolean isNucleotideSequence(String s, boolean allowGaps)
+ {
+ if (s == null)
+ {
+ return false;
+ }
+ for (int i = 0; i < s.length(); i++)
+ {
+ char c = s.charAt(i);
+ if (!isNucleotide(c))
+ {
+ if (!allowGaps || !isGap(c))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
* Convenience overload of isNucleotide
*
* @param seqs
protected AlignmentViewport av;
+ /*
+ * map holds per feature type, {{min, max}, {min, max}} feature score
+ * values for positional and non-positional features respectively
+ */
+ private Map<String, float[][]> minmax = new Hashtable<String, float[][]>();
+
@Override
public AlignViewportI getViewport()
{
renderOrder = neworder;
}
- protected Hashtable minmax = new Hashtable();
-
- public Hashtable getMinMax()
+ public Map<String, float[][]> getMinMax()
{
return minmax;
}
*/
protected final byte[] normaliseScore(SequenceFeature sequenceFeature)
{
- float[] mm = ((float[][]) minmax.get(sequenceFeature.type))[0];
+ float[] mm = minmax.get(sequenceFeature.type)[0];
final byte[] r = new byte[] { 0, (byte) 255 };
if (mm != null)
{
}
if (minmax == null)
{
- minmax = new Hashtable();
+ minmax = new Hashtable<String, float[][]>();
}
AlignmentI alignment = av.getAlignment();
for (int i = 0; i < alignment.getHeight(); i++)
if (!Float.isNaN(features[index].score))
{
int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
- float[][] mm = (float[][]) minmax.get(features[index].getType());
+ float[][] mm = minmax.get(features[index].getType());
if (mm == null)
{
mm = new float[][] { null, null };
changeSupport.removePropertyChangeListener(listener);
}
- public Set getAllFeatureColours()
+ public Set<String> getAllFeatureColours()
{
return featureColours.keySet();
}
protected AlignmentViewPanel ap;
- protected List<AlignmentAnnotation> ourAnnots = null;
+ protected List<AlignmentAnnotation> ourAnnots;
public AlignCalcWorker(AlignViewportI alignViewport,
AlignmentViewPanel alignPanel)
}
+ @Override
public boolean involves(AlignmentAnnotation i)
{
return ourAnnots != null && ourAnnots.contains(i);
}
/**
- * permanently remove from the alignment all annotation rows managed by this
+ * Permanently removes from the alignment all annotation rows managed by this
* worker
*/
@Override
- public void removeOurAnnotation()
+ public void removeAnnotation()
{
if (ourAnnots != null && alignViewport != null)
{
alignment.deleteAnnotation(aa, true);
}
}
+ ourAnnots.clear();
}
}
// TODO: allow GUI to query workers associated with annotation to add items to
--- /dev/null
+package jalview.workers;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.Annotation;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
+
+import java.awt.Color;
+
+/**
+ * Factory class with methods which allow clients (including external scripts
+ * such as Groovy) to 'register and forget' an alignment annotation calculator. <br>
+ * Currently supports two flavours of calculator:
+ * <ul>
+ * <li>a 'feature counter' which can count any desired property derivable from
+ * residue value and any sequence features at each position of the alignment</li>
+ * <li>a 'general purpose' calculator which computes one more complete
+ * AlignmentAnnotation objects</li>
+ * </ul>
+ */
+public class AlignmentAnnotationFactory
+{
+ /**
+ * Constructs and registers a new alignment annotation worker
+ *
+ * @param counter
+ * provider of feature counts per alignment position
+ */
+ public static void newCalculator(FeatureCounterI counter)
+ {
+ if (Desktop.getCurrentAlignFrame() != null)
+ {
+ newCalculator(Desktop.getCurrentAlignFrame(), counter);
+ }
+ else
+ {
+ System.err
+ .println("Can't register calculator as no alignment window has focus");
+ }
+ }
+
+ /**
+ * Constructs and registers a new alignment annotation worker
+ *
+ * @param af
+ * the AlignFrame for which the annotation is to be calculated
+ * @param counter
+ * provider of feature counts per alignment position
+ */
+ public static void newCalculator(AlignFrame af, FeatureCounterI counter)
+ {
+ new ColumnCounterWorker(af, counter);
+ }
+
+ /**
+ * Constructs and registers a new alignment annotation worker
+ *
+ * @param calculator
+ * provider of AlignmentAnnotation for the alignment
+ */
+ public static void newCalculator(AnnotationProviderI calculator)
+ {
+ if (Desktop.getCurrentAlignFrame() != null)
+ {
+ newCalculator(Desktop.getCurrentAlignFrame(), calculator);
+ }
+ else
+ {
+ System.err
+ .println("Can't register calculator as no alignment window has focus");
+ }
+ }
+
+ /**
+ * Constructs and registers a new alignment annotation worker
+ *
+ * @param af
+ * the AlignFrame for which the annotation is to be calculated
+ * @param calculator
+ * provider of AlignmentAnnotation for the alignment
+ */
+ public static void newCalculator(AlignFrame af,
+ AnnotationProviderI calculator)
+ {
+ new AnnotationWorker(af, calculator);
+ }
+
+ /**
+ * Factory method to construct an Annotation object
+ *
+ * @param displayChar
+ * @param desc
+ * @param secondaryStructure
+ * @param val
+ * @param color
+ * @return
+ */
+ public static Annotation newAnnotation(String displayChar, String desc,
+ char secondaryStructure, float val, Color color)
+ {
+ return new Annotation(displayChar, desc, secondaryStructure, val, color);
+ }
+
+ /**
+ * Factory method to construct an AlignmentAnnotation object
+ *
+ * @param name
+ * @param desc
+ * @param anns
+ * @return
+ */
+ public static AlignmentAnnotation newAlignmentAnnotation(String name,
+ String desc, Annotation[] anns)
+ {
+ return new AlignmentAnnotation(name, desc, anns);
+ }
+}
--- /dev/null
+package jalview.workers;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.gui.FeatureRenderer;
+
+import java.util.List;
+
+/**
+ * Interface to be satisfied by any class which computes one or more alignment
+ * annotations
+ */
+public interface AnnotationProviderI
+{
+ List<AlignmentAnnotation> calculateAnnotation(AlignmentI al,
+ FeatureRenderer fr);
+}
--- /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.workers;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.gui.AlignFrame;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.FeatureRenderer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A class to create and update one or more alignment annotations, given a
+ * 'calculator'.
+ *
+ */
+class AnnotationWorker extends AlignCalcWorker
+{
+ /*
+ * the provider of the annotation calculations
+ */
+ AnnotationProviderI counter;
+
+ /**
+ * Constructor
+ *
+ * @param af
+ * @param counter
+ */
+ public AnnotationWorker(AlignFrame af, AnnotationProviderI counter)
+ {
+ super(af.getViewport(), af.alignPanel);
+ ourAnnots = new ArrayList<AlignmentAnnotation>();
+ this.counter = counter;
+ calcMan.registerWorker(this);
+ }
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ calcMan.notifyStart(this);
+
+ while (!calcMan.notifyWorking(this))
+ {
+ try
+ {
+ Thread.sleep(200);
+ } catch (InterruptedException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ if (alignViewport.isClosed())
+ {
+ abortAndDestroy();
+ return;
+ }
+
+ removeAnnotations();
+ AlignmentI alignment = alignViewport.getAlignment();
+ if (alignment != null)
+ {
+ try
+ {
+ List<AlignmentAnnotation> anns = counter.calculateAnnotation(
+ alignment, new FeatureRenderer((AlignmentPanel) ap));
+ for (AlignmentAnnotation ann : anns)
+ {
+ ann.showAllColLabels = true;
+ ann.graph = AlignmentAnnotation.BAR_GRAPH;
+ ourAnnots.add(ann);
+ alignment.addAnnotation(ann);
+ }
+ } catch (IndexOutOfBoundsException x)
+ {
+ // probable race condition. just finish and return without any fuss.
+ return;
+ }
+ }
+ } catch (OutOfMemoryError error)
+ {
+ ap.raiseOOMWarning("calculating annotations", error);
+ calcMan.workerCannotRun(this);
+ } finally
+ {
+ calcMan.workerComplete(this);
+ }
+
+ if (ap != null)
+ {
+ ap.adjustAnnotationHeight();
+ ap.paintAlignment(true);
+ }
+
+ }
+
+ /**
+ * Remove all our annotations before re-calculating them
+ */
+ void removeAnnotations()
+ {
+ for (AlignmentAnnotation ann : ourAnnots)
+ {
+ alignViewport.getAlignment().deleteAnnotation(ann);
+ }
+ ourAnnots.clear();
+ }
+
+ @Override
+ public void updateAnnotation()
+ {
+ // do nothing
+ }
+}
--- /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.workers;
+
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.AlignmentPanel;
+import jalview.gui.FeatureRenderer;
+import jalview.util.ColorUtils;
+import jalview.util.Comparison;
+
+import java.awt.Color;
+import java.util.ArrayList;
+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>
+ * 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.
+ *
+ */
+class ColumnCounterWorker extends AlignCalcWorker
+{
+ FeatureCounterI counter;
+
+ /**
+ * Constructor registers the annotation for the given alignment frame
+ *
+ * @param af
+ * @param counter
+ */
+ public ColumnCounterWorker(AlignFrame af, FeatureCounterI counter)
+ {
+ super(af.getViewport(), af.alignPanel);
+ ourAnnots = new ArrayList<AlignmentAnnotation>();
+ this.counter = counter;
+ calcMan.registerWorker(this);
+ }
+
+ /**
+ * method called under control of AlignCalcManager to recompute the annotation
+ * when the alignment changes
+ */
+ @Override
+ public void run()
+ {
+ try
+ {
+ calcMan.notifyStart(this);
+
+ while (!calcMan.notifyWorking(this))
+ {
+ try
+ {
+ Thread.sleep(200);
+ } catch (InterruptedException ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ if (alignViewport.isClosed())
+ {
+ abortAndDestroy();
+ return;
+ }
+
+ removeAnnotation();
+ if (alignViewport.getAlignment() != null)
+ {
+ try
+ {
+ computeAnnotations();
+ } catch (IndexOutOfBoundsException x)
+ {
+ // probable race condition. just finish and return without any fuss.
+ return;
+ }
+ }
+ } catch (OutOfMemoryError error)
+ {
+ ap.raiseOOMWarning("calculating feature counts", error);
+ calcMan.workerCannotRun(this);
+ } finally
+ {
+ calcMan.workerComplete(this);
+ }
+
+ if (ap != null)
+ {
+ 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.
+ */
+ void computeAnnotations()
+ {
+ FeatureRenderer fr = new FeatureRenderer((AlignmentPanel) ap);
+ // TODO use the commented out code once JAL-2075 is fixed
+ // to get adequate performance on genomic length sequence
+ AlignmentI alignment = alignViewport.getAlignment();
+ // AlignmentView alignmentView = alignViewport.getAlignmentView(false);
+ // AlignmentI alignment = alignmentView.getVisibleAlignment(' ');
+
+ // int width = alignmentView.getWidth();
+ int width = alignment.getWidth();
+ int height = alignment.getHeight();
+ int[] counts = new int[width];
+ int max = 0;
+
+ for (int col = 0; col < width; col++)
+ {
+ int count = 0;
+ for (int row = 0; row < height; row++)
+ {
+ count += countFeaturesAt(alignment, col, row, fr);
+ }
+ counts[col] = count;
+ max = Math.max(count, max);
+ }
+
+ Annotation[] anns = new Annotation[width];
+ /*
+ * add non-zero counts as annotations
+ */
+ for (int i = 0; i < counts.length; i++)
+ {
+ int count = counts[i];
+ if (count > 0)
+ {
+ Color color = ColorUtils.getGraduatedColour(count, 0, Color.cyan,
+ max, Color.blue);
+ anns[i] = new Annotation(String.valueOf(count),
+ String.valueOf(count), '0', count, color);
+ }
+ }
+
+ /*
+ * construct the annotation, save it and add it to the displayed alignment
+ */
+ AlignmentAnnotation ann = new AlignmentAnnotation(counter.getName(),
+ counter.getDescription(), anns);
+ ann.showAllColLabels = true;
+ ann.graph = AlignmentAnnotation.BAR_GRAPH;
+ ourAnnots.add(ann);
+ alignViewport.getAlignment().addAnnotation(ann);
+ }
+
+ /**
+ * Returns a count of any feature types present at the specified position of
+ * the alignment
+ *
+ * @param alignment
+ * @param col
+ * @param row
+ * @param fr
+ */
+ int countFeaturesAt(AlignmentI alignment, int col, int row,
+ FeatureRenderer fr)
+ {
+ SequenceI seq = alignment.getSequenceAt(row);
+ if (seq == null)
+ {
+ return 0;
+ }
+ if (col >= seq.getLength())
+ {
+ return 0;// sequence doesn't extend this far
+ }
+ char res = seq.getCharAt(col);
+ if (Comparison.isGap(res))
+ {
+ return 0;
+ }
+ int pos = seq.findPosition(col);
+
+ /*
+ * compute a count for any displayed features at residue
+ */
+ // 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);
+ return count;
+ }
+
+ /**
+ * Method called when the user changes display options that may affect how the
+ * annotation is rendered, but do not change its values. Currently no such
+ * options affect user-defined annotation, so this method does nothing.
+ */
+ @Override
+ public void updateAnnotation()
+ {
+ // do nothing
+ }
+}
package jalview.workers;
import jalview.analysis.AAFrequency;
-import jalview.api.AlignCalcWorkerI;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.datamodel.AlignmentAnnotation;
import java.util.Hashtable;
-public class ConsensusThread extends AlignCalcWorker implements
- AlignCalcWorkerI
+public class ConsensusThread extends AlignCalcWorker
{
public ConsensusThread(AlignViewportI alignViewport,
AlignmentViewPanel alignPanel)
package jalview.workers;
import jalview.analysis.Conservation;
-import jalview.api.AlignCalcWorkerI;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.datamodel.AlignmentAnnotation;
import java.util.ArrayList;
import java.util.List;
-public class ConservationThread extends AlignCalcWorker implements
- AlignCalcWorkerI
+public class ConservationThread extends AlignCalcWorker
{
private int ConsPercGaps = 25; // JBPNote : This should be a configurable
--- /dev/null
+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
+ *
+ */
+public interface FeatureCounterI
+{
+ /**
+ * Returns a count of some property 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>
+ * <li>1 if the residue is hydrophobic, else 0</li>
+ * <li>etc</li>
+ * </ul>
+ *
+ * @param residue
+ * the residue (or gap) at the position
+ * @param a
+ * list of any sequence features which include the position
+ */
+ int count(String residue, List<SequenceFeature> features);
+
+ /**
+ * Returns a name for the annotation that this is counting, for use as the
+ * displayed label
+ *
+ * @return
+ */
+ String getName();
+
+ /**
+ * Returns a description for the annotation, for display as a tooltip
+ *
+ * @return
+ */
+ String getDescription();
+
+ /**
+ * Returns the colour (as [red, green, blue] values in the range 0-255) to use
+ * for the minimum value on histogram bars. If this is different to
+ * getMaxColour(), then bars will have a graduated colour.
+ *
+ * @return
+ */
+ int[] getMinColour();
+
+ /**
+ * Returns the colour (as [red, green, blue] values in the range 0-255) to use
+ * for the maximum value on histogram bars. If this is the same as
+ * getMinColour(), then bars will have a single colour (not graduated).
+ *
+ * @return
+ */
+ int[] getMaxColour();
+}
package jalview.workers;
import jalview.analysis.StructureFrequency;
-import jalview.api.AlignCalcWorkerI;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.datamodel.AlignmentAnnotation;
import java.util.Hashtable;
-public class StrucConsensusThread extends AlignCalcWorker implements
- AlignCalcWorkerI
+public class StrucConsensusThread extends AlignCalcWorker
{
public StrucConsensusThread(AlignViewportI alignViewport,
AlignmentViewPanel alignPanel)
*/
package jalview.ws.jws2;
-import jalview.api.AlignCalcWorkerI;
import jalview.bin.Cache;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.GraphLine;
import compbio.data.sequence.ScoreManager.ScoreHolder;
import compbio.metadata.Argument;
-public class AADisorderClient extends JabawsCalcWorker implements
- AlignCalcWorkerI
+public class AADisorderClient extends JabawsCalcWorker
{
private static final String THRESHOLD = "THRESHOLD";
*/
package jalview.ws.jws2;
-import jalview.api.AlignCalcWorkerI;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.gui.AlignFrame;
import compbio.metadata.Argument;
public class JPred301Client extends JabawsMsaInterfaceAlignCalcWorker
- implements AlignCalcWorkerI
{
-
/**
*
* @return default args for this service when run as dynamic web service
return (seqs.size() > 1);
}
+ @Override
public String getServiceActionText()
{
return "calculating consensus secondary structure prediction using JPred service";
* update the consensus annotation from the sequence profile data using
* current visualization settings.
*/
+ @Override
public void updateResultAnnotation(boolean immediate)
{
if (immediate || !calcMan.isWorking(this) && msascoreset != null)
*/
package jalview.ws.jws2;
-import jalview.api.AlignCalcWorkerI;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.Annotation;
import jalview.gui.AlignFrame;
*
*/
-public class RNAalifoldClient extends JabawsCalcWorker implements
- AlignCalcWorkerI
+public class RNAalifoldClient extends JabawsCalcWorker
{
String methodName;
initViewportParams();
}
+ @Override
public String getCalcId()
{
return CALC_ID;
import static org.testng.AssertJUnit.assertSame;
import static org.testng.AssertJUnit.assertTrue;
+import jalview.analysis.AlignmentUtils.DnaVariant;
import jalview.datamodel.AlignedCodonFrame;
import jalview.datamodel.Alignment;
import jalview.datamodel.AlignmentAnnotation;
/*
* first with no variants on dna
*/
- LinkedHashMap<Integer, List<String[][]>> variantsMap = AlignmentUtils
+ LinkedHashMap<Integer, List<DnaVariant>[]> variantsMap = AlignmentUtils
.buildDnaVariantsMap(dna, map);
assertTrue(variantsMap.isEmpty());
/*
* single allele codon 1, on base 1
*/
- SequenceFeature sf = new SequenceFeature("sequence_variant", "", 1, 1,
+ SequenceFeature sf1 = new SequenceFeature("sequence_variant", "", 1, 1,
0f, null);
- sf.setValue("alleles", "T");
- sf.setValue("ID", "sequence_variant:rs758803211");
- dna.addSequenceFeature(sf);
+ sf1.setValue("alleles", "T");
+ sf1.setValue("ID", "sequence_variant:rs758803211");
+ dna.addSequenceFeature(sf1);
/*
* two alleles codon 2, on bases 2 and 3 (distinct variants)
*/
- sf = new SequenceFeature("sequence_variant", "", 5, 5, 0f, null);
- sf.setValue("alleles", "T");
- sf.setValue("ID", "sequence_variant:rs758803212");
- dna.addSequenceFeature(sf);
- sf = new SequenceFeature("sequence_variant", "", 6, 6, 0f, null);
- sf.setValue("alleles", "G");
- sf.setValue("ID", "sequence_variant:rs758803213");
- dna.addSequenceFeature(sf);
+ SequenceFeature sf2 = new SequenceFeature("sequence_variant", "", 5, 5,
+ 0f, null);
+ sf2.setValue("alleles", "T");
+ sf2.setValue("ID", "sequence_variant:rs758803212");
+ dna.addSequenceFeature(sf2);
+ SequenceFeature sf3 = new SequenceFeature("sequence_variant", "", 6, 6,
+ 0f, null);
+ sf3.setValue("alleles", "G");
+ sf3.setValue("ID", "sequence_variant:rs758803213");
+ dna.addSequenceFeature(sf3);
/*
* two alleles codon 3, both on base 2 (one variant)
*/
- sf = new SequenceFeature("sequence_variant", "", 8, 8, 0f, null);
- sf.setValue("alleles", "C, G");
- sf.setValue("ID", "sequence_variant:rs758803214");
- dna.addSequenceFeature(sf);
+ SequenceFeature sf4 = new SequenceFeature("sequence_variant", "", 8, 8,
+ 0f, null);
+ sf4.setValue("alleles", "C, G");
+ sf4.setValue("ID", "sequence_variant:rs758803214");
+ dna.addSequenceFeature(sf4);
// no alleles on codon 4
/*
* alleles on codon 5 on all 3 bases (distinct variants)
*/
- sf = new SequenceFeature("sequence_variant", "", 13, 13, 0f, null);
- sf.setValue("alleles", "C, G"); // (C duplicates given base value)
- sf.setValue("ID", "sequence_variant:rs758803215");
- dna.addSequenceFeature(sf);
- sf = new SequenceFeature("sequence_variant", "", 14, 14, 0f, null);
- sf.setValue("alleles", "g, a"); // should force to upper-case
- sf.setValue("ID", "sequence_variant:rs758803216");
- dna.addSequenceFeature(sf);
- sf = new SequenceFeature("sequence_variant", "", 15, 15, 0f, null);
- sf.setValue("alleles", "A, T");
- sf.setValue("ID", "sequence_variant:rs758803217");
- dna.addSequenceFeature(sf);
+ SequenceFeature sf5 = new SequenceFeature("sequence_variant", "", 13,
+ 13, 0f, null);
+ sf5.setValue("alleles", "C, G"); // (C duplicates given base value)
+ sf5.setValue("ID", "sequence_variant:rs758803215");
+ dna.addSequenceFeature(sf5);
+ SequenceFeature sf6 = new SequenceFeature("sequence_variant", "", 14,
+ 14, 0f, null);
+ sf6.setValue("alleles", "g, a"); // should force to upper-case
+ sf6.setValue("ID", "sequence_variant:rs758803216");
+ dna.addSequenceFeature(sf6);
+ SequenceFeature sf7 = new SequenceFeature("sequence_variant", "", 15,
+ 15, 0f, null);
+ sf7.setValue("alleles", "A, T");
+ sf7.setValue("ID", "sequence_variant:rs758803217");
+ dna.addSequenceFeature(sf7);
/*
* build map - expect variants on positions 1, 2, 3, 5
assertEquals(4, variantsMap.size());
/*
- * one variant on protein position 1
- */
- assertEquals(1, variantsMap.get(1).size());
- assertTrue(Arrays.deepEquals(new String[][] { { "A", "T" }, { "T" },
- { "G" } }, variantsMap.get(1).get(0)));
-
- /*
- * two variants on protein position 2
- */
- assertEquals(2, variantsMap.get(2).size());
- assertTrue(Arrays.deepEquals(new String[][] { { "A" }, { "A", "T" },
- { "A" } }, variantsMap.get(2).get(0)));
- assertTrue(Arrays.deepEquals(new String[][] { { "A" }, { "A" },
- { "A", "G" } }, variantsMap.get(2).get(1)));
-
- /*
- * one variant on protein position 3
- */
- assertEquals(1, variantsMap.get(3).size());
- assertTrue(Arrays.deepEquals(new String[][] { { "T" },
- { "T", "C", "G" }, { "T" } }, variantsMap.get(3).get(0)));
+ * protein residue 1: variant on codon (ATG) base 1, not on 2 or 3
+ */
+ List<DnaVariant>[] pep1Variants = variantsMap.get(1);
+ assertEquals(3, pep1Variants.length);
+ assertEquals(1, pep1Variants[0].size());
+ assertEquals("A", pep1Variants[0].get(0).base); // codon[1] base
+ assertSame(sf1, pep1Variants[0].get(0).variant); // codon[1] variant
+ assertEquals(1, pep1Variants[1].size());
+ assertEquals("T", pep1Variants[1].get(0).base); // codon[2] base
+ assertNull(pep1Variants[1].get(0).variant); // no variant here
+ assertEquals(1, pep1Variants[2].size());
+ assertEquals("G", pep1Variants[2].get(0).base); // codon[3] base
+ assertNull(pep1Variants[2].get(0).variant); // no variant here
+
+ /*
+ * protein residue 2: variants on codon (AAA) bases 2 and 3
+ */
+ List<DnaVariant>[] pep2Variants = variantsMap.get(2);
+ assertEquals(3, pep2Variants.length);
+ assertEquals(1, pep2Variants[0].size());
+ // codon[1] base recorded while processing variant on codon[2]
+ assertEquals("A", pep2Variants[0].get(0).base);
+ assertNull(pep2Variants[0].get(0).variant); // no variant here
+ // codon[2] base and variant:
+ assertEquals(1, pep2Variants[1].size());
+ assertEquals("A", pep2Variants[1].get(0).base);
+ assertSame(sf2, pep2Variants[1].get(0).variant);
+ // codon[3] base was recorded when processing codon[2] variant
+ // and then the variant for codon[3] added to it
+ assertEquals(1, pep2Variants[2].size());
+ assertEquals("A", pep2Variants[2].get(0).base);
+ assertSame(sf3, pep2Variants[2].get(0).variant);
+
+ /*
+ * protein residue 3: variants on codon (TTT) base 2 only
+ */
+ List<DnaVariant>[] pep3Variants = variantsMap.get(3);
+ assertEquals(3, pep3Variants.length);
+ assertEquals(1, pep3Variants[0].size());
+ assertEquals("T", pep3Variants[0].get(0).base); // codon[1] base
+ assertNull(pep3Variants[0].get(0).variant); // no variant here
+ assertEquals(1, pep3Variants[1].size());
+ assertEquals("T", pep3Variants[1].get(0).base); // codon[2] base
+ assertSame(sf4, pep3Variants[1].get(0).variant); // codon[2] variant
+ assertEquals(1, pep3Variants[2].size());
+ assertEquals("T", pep3Variants[2].get(0).base); // codon[3] base
+ assertNull(pep3Variants[2].get(0).variant); // no variant here
/*
* three variants on protein position 5
- * duplicated bases are not removed here, handled in computePeptideVariants
- */
- assertEquals(3, variantsMap.get(5).size());
- assertTrue(Arrays.deepEquals(new String[][] { { "C", "C", "G" },
- { "C" }, { "C" } }, variantsMap.get(5).get(0)));
- assertTrue(Arrays.deepEquals(new String[][] { { "C" },
- { "C", "G", "A" }, { "C" } }, variantsMap.get(5).get(1)));
- assertTrue(Arrays.deepEquals(new String[][] { { "C" }, { "C" },
- { "C", "A", "T" } }, variantsMap.get(5).get(2)));
+ */
+ List<DnaVariant>[] pep5Variants = variantsMap.get(5);
+ assertEquals(3, pep5Variants.length);
+ assertEquals(1, pep5Variants[0].size());
+ assertEquals("C", pep5Variants[0].get(0).base); // codon[1] base
+ assertSame(sf5, pep5Variants[0].get(0).variant); // codon[1] variant
+ assertEquals(1, pep5Variants[1].size());
+ assertEquals("C", pep5Variants[1].get(0).base); // codon[2] base
+ assertSame(sf6, pep5Variants[1].get(0).variant); // codon[2] variant
+ assertEquals(1, pep5Variants[2].size());
+ assertEquals("C", pep5Variants[2].get(0).base); // codon[3] base
+ assertSame(sf7, pep5Variants[2].get(0).variant); // codon[3] variant
}
/**
@Test(groups = "Functional")
public void testComputePeptideVariants()
{
- String[][] codonVariants = new String[][] { { "A" }, { "G" }, { "T" } };
-
/*
- * AGT codes for S - this is not included in the variants returned
+ * scenario: AAATTTCCC codes for KFP, with variants
+ * GAA -> E
+ * CAA -> Q
+ * AAG synonymous
+ * AAT -> N
+ * TTC synonymous
+ * CAC,CGC -> H,R (as one variant)
*/
- List<String> variants = AlignmentUtils.computePeptideVariants(codonVariants, "S");
- assertEquals("[]", variants.toString());
-
- // S is reported if it differs from the current value (A):
- variants = AlignmentUtils.computePeptideVariants(codonVariants, "A");
- assertEquals("[S]", variants.toString());
-
- /*
- * synonymous variant is not reported
- */
- codonVariants = new String[][] { { "A" }, { "G" }, { "C", "T" } };
- // AGC and AGT both code for S
- variants = AlignmentUtils.computePeptideVariants(codonVariants, "s");
- assertEquals("[]", variants.toString());
-
+ SequenceI peptide = new Sequence("pep/10-12", "KFP");
+
/*
- * equivalent variants are only reported once
+ * two distinct variants for codon 1 position 1
+ * second one has clinical significance
*/
- codonVariants = new String[][] { { "C" }, { "T" },
- { "A", "C", "G", "T" } };
- // CTA CTC CTG CTT all code for L
- variants = AlignmentUtils.computePeptideVariants(codonVariants, "S");
- assertEquals("[L]", variants.toString());
-
+ SequenceFeature sf1 = new SequenceFeature("sequence_variant", "", 1, 1,
+ 0f, null);
+ sf1.setValue("alleles", "A,G"); // GAA -> E
+ sf1.setValue("ID", "var1.125A>G");
+ SequenceFeature sf2 = new SequenceFeature("sequence_variant", "", 1, 1,
+ 0f, null);
+ sf2.setValue("alleles", "A,C"); // CAA -> Q
+ sf2.setValue("ID", "var2");
+ sf2.setValue("clinical_significance", "Dodgy");
+ SequenceFeature sf3 = new SequenceFeature("sequence_variant", "", 3, 3,
+ 0f, null);
+ sf3.setValue("alleles", "A,G"); // synonymous
+ sf3.setValue("ID", "var3");
+ sf3.setValue("clinical_significance", "None");
+ SequenceFeature sf4 = new SequenceFeature("sequence_variant", "", 3, 3,
+ 0f, null);
+ sf4.setValue("alleles", "A,T"); // AAT -> N
+ sf4.setValue("ID", "sequence_variant:var4"); // prefix gets stripped off
+ sf4.setValue("clinical_significance", "Benign");
+ SequenceFeature sf5 = new SequenceFeature("sequence_variant", "", 6, 6,
+ 0f, null);
+ sf5.setValue("alleles", "T,C"); // synonymous
+ sf5.setValue("ID", "var5");
+ sf5.setValue("clinical_significance", "Bad");
+ SequenceFeature sf6 = new SequenceFeature("sequence_variant", "", 8, 8,
+ 0f, null);
+ sf6.setValue("alleles", "C,A,G"); // CAC,CGC -> H,R
+ sf6.setValue("ID", "var6");
+ sf6.setValue("clinical_significance", "Good");
+
+ List<DnaVariant> codon1Variants = new ArrayList<DnaVariant>();
+ List<DnaVariant> codon2Variants = new ArrayList<DnaVariant>();
+ List<DnaVariant> codon3Variants = new ArrayList<DnaVariant>();
+ List<DnaVariant> codonVariants[] = new ArrayList[3];
+ codonVariants[0] = codon1Variants;
+ codonVariants[1] = codon2Variants;
+ codonVariants[2] = codon3Variants;
+
/*
- * vary codons 1 and 2; variant products are sorted and non-redundant
+ * compute variants for protein position 1
*/
- codonVariants = new String[][] { { "a", "C" }, { "g", "T" }, { "A" } };
- // aga ata cga cta code for R, I, R, L
- variants = AlignmentUtils.computePeptideVariants(codonVariants, "S");
- assertEquals("[I, L, R]", variants.toString());
-
+ codon1Variants.add(new DnaVariant("A", sf1));
+ codon1Variants.add(new DnaVariant("A", sf2));
+ codon2Variants.add(new DnaVariant("A"));
+ codon2Variants.add(new DnaVariant("A"));
+ codon3Variants.add(new DnaVariant("A", sf3));
+ codon3Variants.add(new DnaVariant("A", sf4));
+ AlignmentUtils.computePeptideVariants(peptide, 1, codonVariants);
+
/*
- * vary codons 2 and 3
+ * compute variants for protein position 2
*/
- codonVariants = new String[][] { { "a" }, { "g", "T" }, { "A", "c" } };
- // aga agc ata atc code for R, S, I, I
- variants = AlignmentUtils.computePeptideVariants(codonVariants, "S");
- assertEquals("[I, R]", variants.toString());
-
+ codon1Variants.clear();
+ codon2Variants.clear();
+ codon3Variants.clear();
+ codon1Variants.add(new DnaVariant("T"));
+ codon2Variants.add(new DnaVariant("T"));
+ codon3Variants.add(new DnaVariant("T", sf5));
+ AlignmentUtils.computePeptideVariants(peptide, 2, codonVariants);
+
/*
- * vary codons 1 and 3
+ * compute variants for protein position 3
*/
- codonVariants = new String[][] { { "a", "t" }, { "a" }, { "t", "g" } };
- // aat aag tat tag code for N, K, Y, STOP - STOP sorted to end
- variants = AlignmentUtils.computePeptideVariants(codonVariants, "S");
- assertEquals("[K, N, Y, STOP]", variants.toString());
-
+ codon1Variants.clear();
+ codon2Variants.clear();
+ codon3Variants.clear();
+ codon1Variants.add(new DnaVariant("C"));
+ codon2Variants.add(new DnaVariant("C", sf6));
+ codon3Variants.add(new DnaVariant("C"));
+ AlignmentUtils.computePeptideVariants(peptide, 3, codonVariants);
+
/*
- * vary codons 1, 2 and 3
+ * verify added sequence features for
+ * var1 K -> E
+ * var2 K -> Q
+ * var4 K -> N
+ * var6 P -> H
+ * var6 P -> R
*/
- codonVariants = new String[][] { { "a", "t" }, { "G", "C" },
- { "t", "g" } };
- // agt agg act acg tgt tgg tct tcg code for S, R, T, T, C, W, S, S
- variants = AlignmentUtils.computePeptideVariants(codonVariants, "S");
- assertEquals("[C, R, T, W]", variants.toString());
+ SequenceFeature[] sfs = peptide.getSequenceFeatures();
+ assertEquals(5, sfs.length);
+ SequenceFeature sf = sfs[0];
+ assertEquals(1, sf.getBegin());
+ assertEquals(1, sf.getEnd());
+ assertEquals("K->E", sf.getDescription());
+ assertEquals("var1.125A>G", sf.getValue("ID"));
+ assertNull(sf.getValue("clinical_significance"));
+ assertEquals("ID=var1.125A>G", sf.getAttributes());
+ assertEquals(1, sf.links.size());
+ // link to variation is urlencoded
+ assertEquals(
+ "K->E var1.125A>G|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var1.125A%3EG",
+ sf.links.get(0));
+ sf = sfs[1];
+ assertEquals(1, sf.getBegin());
+ assertEquals(1, sf.getEnd());
+ assertEquals("K->Q", sf.getDescription());
+ assertEquals("var2", sf.getValue("ID"));
+ assertEquals("Dodgy", sf.getValue("clinical_significance"));
+ assertEquals("ID=var2;clinical_significance=Dodgy", sf.getAttributes());
+ assertEquals(1, sf.links.size());
+ assertEquals(
+ "K->Q var2|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var2",
+ sf.links.get(0));
+ sf = sfs[2];
+ assertEquals(1, sf.getBegin());
+ assertEquals(1, sf.getEnd());
+ assertEquals("K->N", sf.getDescription());
+ assertEquals("var4", sf.getValue("ID"));
+ assertEquals("Benign", sf.getValue("clinical_significance"));
+ assertEquals("ID=var4;clinical_significance=Benign", sf.getAttributes());
+ assertEquals(1, sf.links.size());
+ assertEquals(
+ "K->N var4|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var4",
+ sf.links.get(0));
+ sf = sfs[3];
+ assertEquals(3, sf.getBegin());
+ assertEquals(3, sf.getEnd());
+ assertEquals("P->H", sf.getDescription());
+ assertEquals("var6", sf.getValue("ID"));
+ assertEquals("Good", sf.getValue("clinical_significance"));
+ assertEquals("ID=var6;clinical_significance=Good", sf.getAttributes());
+ assertEquals(1, sf.links.size());
+ assertEquals(
+ "P->H var6|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var6",
+ sf.links.get(0));
+ // var5 generates two distinct protein variant features
+ sf = sfs[4];
+ assertEquals(3, sf.getBegin());
+ assertEquals(3, sf.getEnd());
+ assertEquals("P->R", sf.getDescription());
+ assertEquals("var6", sf.getValue("ID"));
+ assertEquals("Good", sf.getValue("clinical_significance"));
+ assertEquals("ID=var6;clinical_significance=Good", sf.getAttributes());
+ assertEquals(1, sf.links.size());
+ assertEquals(
+ "P->R var6|http://www.ensembl.org/Homo_sapiens/Variation/Summary?v=var6",
+ sf.links.get(0));
}
/**
import jalview.io.FileLoader;
import jalview.io.FormatAdapter;
-import org.testng.AssertJUnit;
+import org.testng.Assert;
import org.testng.annotations.Test;
public class FeatureScoreModelTest
int[] sf3 = new int[] { -1, -1, -1, -1, -1, -1, 76, 77 };
- @Test(groups = { "Functional" })
- public void testFeatureScoreModel() throws Exception
+ public AlignFrame getTestAlignmentFrame()
{
AlignFrame alf = new FileLoader(false).LoadFileWaitTillLoaded(
alntestFile, FormatAdapter.PASTE);
AlignmentI al = alf.getViewport().getAlignment();
- AssertJUnit.assertEquals(4, al.getHeight());
- AssertJUnit.assertEquals(5, al.getWidth());
+ Assert.assertEquals(al.getHeight(), 4);
+ Assert.assertEquals(al.getWidth(), 5);
for (int i = 0; i < 4; i++)
{
SequenceI ds = al.getSequenceAt(i).getDatasetSequence();
alf.getFeatureRenderer().setVisible("sf2");
alf.getFeatureRenderer().setVisible("sf3");
alf.getFeatureRenderer().findAllFeatures(true);
- AssertJUnit.assertEquals("Number of feature types", 3, alf
- .getFeatureRenderer().getDisplayedFeatureTypes().size());
- AssertJUnit.assertTrue(alf.getCurrentView().areFeaturesDisplayed());
+ Assert.assertEquals(alf.getFeatureRenderer().getDisplayedFeatureTypes()
+ .size(), 3, "Number of feature types");
+ Assert.assertTrue(alf.getCurrentView().areFeaturesDisplayed());
+ return alf;
+ }
+
+ @Test(groups = { "Functional" })
+ public void testFeatureScoreModel() throws Exception
+ {
+ AlignFrame alf = getTestAlignmentFrame();
FeatureScoreModel fsm = new FeatureScoreModel();
- AssertJUnit.assertTrue(fsm.configureFromAlignmentView(alf
+ Assert.assertTrue(fsm.configureFromAlignmentView(alf
.getCurrentView().getAlignPanel()));
alf.selectAllSequenceMenuItem_actionPerformed(null);
float[][] dm = fsm.findDistances(alf.getViewport().getAlignmentView(
true));
- AssertJUnit.assertTrue("FER1_MESCR should be identical with RAPSA (2)",
- dm[0][2] == 0f);
- AssertJUnit
- .assertTrue(
- "FER1_MESCR should be further from SPIOL (1) than it is from RAPSA (2)",
- dm[0][1] > dm[0][2]);
+ Assert.assertTrue(dm[0][2] == 0f,
+ "FER1_MESCR (0) should be identical with RAPSA (2)");
+ Assert.assertTrue(dm[0][1] > dm[0][2],
+ "FER1_MESCR (0) should be further from SPIOL (1) than it is from RAPSA (2)");
+ }
+
+ @Test(groups = { "Functional" })
+ public void testFeatureScoreModel_hiddenFirstColumn() throws Exception
+ {
+ 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()
+ .getAlignPanel()));
+ alf.selectAllSequenceMenuItem_actionPerformed(null);
+ float[][] dm = fsm.findDistances(alf.getViewport().getAlignmentView(
+ true));
+ Assert.assertTrue(dm[0][2] == 0f,
+ "FER1_MESCR (0) should be identical with RAPSA (2)");
+ Assert.assertTrue(dm[0][1] > dm[0][2],
+ "FER1_MESCR (0) should be further from SPIOL (1) than it is from RAPSA (2)");
+ }
+ @Test(groups = { "Functional" })
+ public void testFeatureScoreModel_HiddenColumns() throws Exception
+ {
+ AlignFrame alf = getTestAlignmentFrame();
+ // 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()
+ .getAlignPanel()));
+ alf.selectAllSequenceMenuItem_actionPerformed(null);
+ float[][] dm = fsm.findDistances(alf.getViewport().getAlignmentView(
+ true));
+ Assert.assertTrue(dm[0][2] == 0f,
+ "After hiding last two columns FER1_MESCR (0) should still be identical with RAPSA (2)");
+ Assert.assertTrue(dm[0][1] == 0f,
+ "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 "
+ + alf.getViewport().getAlignment().getSequenceAt(s).getName()
+ + "(" + s + ") should still be distinct from FER1_MAIZE (3)");
+ }
}
}
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
+import jalview.util.Comparison;
+
import org.testng.annotations.Test;
/**
*/
public class SeqCigarTest
{
+ @Test(groups = { "Functional" })
+ public void testFindPosition()
+ {
+ SequenceI oseq = new Sequence("MySeq", "ASD---ASD---ASD", 37, 45);
+ oseq.createDatasetSequence();
+ SeqCigar cs = new SeqCigar(oseq);
+ assertEquals(oseq.getSequenceAsString(), cs.getSequenceString('-'));
+ for (int c = 0, cLen = oseq.getLength(); c < cLen; c++)
+ {
+ int os_p = oseq.findPosition(c);
+ int cigar_p = cs.findPosition(c);
+ if (Comparison.isGap(oseq.getCharAt(c)))
+ {
+ assertEquals("Expected gap at position " + os_p + " column " + c,
+ -1, cigar_p);
+ }
+ else
+ {
+ assertEquals("Positions don't match for at column " + c, os_p,
+ cigar_p);
+ }
+ }
+ }
/*
* refactored 'as is' from main method
*
sb = new StringBuilder();
EnsemblSeqProxy.reverseComplementAllele(sb, "-GATt"); // revcomp=aATC-
EnsemblSeqProxy.reverseComplementAllele(sb, "hgmd_mutation");
- assertEquals("aATC-,hgmd_mutation", sb.toString());
+ EnsemblSeqProxy.reverseComplementAllele(sb, "PhenCode_variation");
+ assertEquals("aATC-,hgmd_mutation,PhenCode_variation", sb.toString());
}
/**
sfs = al.getSequenceAt(2).getDatasetSequence().getSequenceFeatures();
assertEquals(1, sfs.length);
sf = sfs[0];
- assertEquals("uniprot", sf.description);
+ // ID used for description if available
+ assertEquals("$23", sf.description);
assertEquals(55, sf.begin);
assertEquals(130, sf.end);
assertEquals("uniprot", sf.featureGroup);
--- /dev/null
+package jalview.io;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import jalview.datamodel.SequenceFeature;
+
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.testng.annotations.Test;
+
+public class SequenceAnnotationReportTest
+{
+ @Test(groups = "Functional")
+ public void testAppendFeature_disulfideBond()
+ {
+ SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+ StringBuffer sb = new StringBuffer();
+ sb.append("123456");
+ SequenceFeature sf = new SequenceFeature("disulfide bond", "desc", 1,
+ 3, 1.2f, "group");
+
+ // residuePos == 2 does not match start or end of feature, nothing done:
+ sar.appendFeature(sb, 2, null, sf);
+ assertEquals("123456", sb.toString());
+
+ // residuePos == 1 matches start of feature, text appended (but no <br>)
+ // feature score is not included
+ sar.appendFeature(sb, 1, null, sf);
+ assertEquals("123456disulfide bond 1:3", sb.toString());
+
+ // residuePos == 3 matches end of feature, text appended
+ // <br> is prefixed once sb.length() > 6
+ sar.appendFeature(sb, 3, null, sf);
+ assertEquals("123456disulfide bond 1:3<br>disulfide bond 1:3",
+ sb.toString());
+ }
+
+ @Test(groups = "Functional")
+ public void testAppendFeature_status()
+ {
+ SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+ StringBuffer sb = new StringBuffer();
+ SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
+ Float.NaN, "group");
+ sf.setStatus("Confirmed");
+
+ sar.appendFeature(sb, 1, null, sf);
+ assertEquals("METAL 1 3; Fe2-S; (Confirmed)", sb.toString());
+ }
+
+ @Test(groups = "Functional")
+ public void testAppendFeature_withScore()
+ {
+ SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+ StringBuffer sb = new StringBuffer();
+ SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3, 1.3f,
+ "group");
+
+ Map<String, float[][]> minmax = new Hashtable<String, float[][]>();
+ sar.appendFeature(sb, 1, minmax, sf);
+ /*
+ * map has no entry for this feature type - score is not shown:
+ */
+ assertEquals("METAL 1 3; Fe2-S", sb.toString());
+
+ /*
+ * map has entry for this feature type - score is shown:
+ */
+ minmax.put("METAL", new float[][] { { 0f, 1f }, null });
+ sar.appendFeature(sb, 1, minmax, sf);
+ // <br> is appended to a buffer > 6 in length
+ assertEquals("METAL 1 3; Fe2-S<br>METAL 1 3; Fe2-S Score=1.3",
+ sb.toString());
+
+ /*
+ * map has min == max for this feature type - score is not shown:
+ */
+ minmax.put("METAL", new float[][] { { 2f, 2f }, null });
+ sb.setLength(0);
+ sar.appendFeature(sb, 1, minmax, sf);
+ assertEquals("METAL 1 3; Fe2-S", sb.toString());
+ }
+
+ @Test(groups = "Functional")
+ public void testAppendFeature_noScore()
+ {
+ SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+ StringBuffer sb = new StringBuffer();
+ SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
+ Float.NaN, "group");
+
+ sar.appendFeature(sb, 1, null, sf);
+ assertEquals("METAL 1 3; Fe2-S", sb.toString());
+ }
+
+ @Test(groups = "Functional")
+ public void testAppendFeature_clinicalSignificance()
+ {
+ SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+ StringBuffer sb = new StringBuffer();
+ SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3,
+ Float.NaN, "group");
+ sf.setValue("clinical_significance", "Benign");
+
+ sar.appendFeature(sb, 1, null, sf);
+ assertEquals("METAL 1 3; Fe2-S; Benign", sb.toString());
+ }
+
+ @Test(groups = "Functional")
+ public void testAppendFeature_withScoreStatusClinicalSignificance()
+ {
+ SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+ StringBuffer sb = new StringBuffer();
+ SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3, 1.3f,
+ "group");
+ sf.setStatus("Confirmed");
+ sf.setValue("clinical_significance", "Benign");
+ Map<String, float[][]> minmax = new Hashtable<String, float[][]>();
+ minmax.put("METAL", new float[][] { { 0f, 1f }, null });
+ sar.appendFeature(sb, 1, minmax, sf);
+
+ assertEquals("METAL 1 3; Fe2-S Score=1.3; (Confirmed); Benign",
+ sb.toString());
+ }
+
+ @Test(groups = "Functional")
+ public void testAppendFeature_DescEqualsType()
+ {
+ SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+ StringBuffer sb = new StringBuffer();
+ SequenceFeature sf = new SequenceFeature("METAL", "METAL", 1, 3,
+ Float.NaN, "group");
+
+ // description is not included if it duplicates type:
+ sar.appendFeature(sb, 1, null, sf);
+ assertEquals("METAL 1 3", sb.toString());
+
+ sb.setLength(0);
+ sf.setDescription("Metal");
+ // test is case-sensitive:
+ sar.appendFeature(sb, 1, null, sf);
+ assertEquals("METAL 1 3; Metal", sb.toString());
+ }
+
+ @Test(groups = "Functional")
+ public void testAppendFeature_stripHtml()
+ {
+ SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
+ StringBuffer sb = new StringBuffer();
+ SequenceFeature sf = new SequenceFeature("METAL",
+ "<html><body>hello<em>world</em></body></html>", 1, 3,
+ Float.NaN, "group");
+
+ sar.appendFeature(sb, 1, null, sf);
+ // !! strips off </body> but not <body> ??
+ assertEquals("METAL 1 3; <body>hello<em>world</em>",
+ sb.toString());
+
+ sb.setLength(0);
+ sf.setDescription("<br>&kHD>6");
+ sar.appendFeature(sb, 1, null, sf);
+ // if no <html> tag, html-encodes > and < (only):
+ assertEquals("METAL 1 3; <br>&kHD>6", sb.toString());
+ }
+}
assertEquals("#800080", ColorUtils.toTkCode(new Color(128, 0, 128))); // purple
assertEquals("#00ff00", ColorUtils.toTkCode(new Color(0, 255, 0))); // lime
}
+
+ @Test(groups = { "Functional" })
+ public void testGetGraduatedColour()
+ {
+ Color minColour = new Color(100, 100, 100);
+ Color maxColour = new Color(180, 200, 220);
+
+ /*
+ * value half-way between min and max
+ */
+ Color col = ColorUtils.getGraduatedColour(20f, 10f, minColour, 30f,
+ maxColour);
+ assertEquals(140, col.getRed());
+ assertEquals(150, col.getGreen());
+ assertEquals(160, col.getBlue());
+
+ /*
+ * value two-thirds of the way between min and max
+ */
+ col = ColorUtils
+ .getGraduatedColour(30f, 10f, minColour, 40f, maxColour);
+ assertEquals(153, col.getRed());
+ // Color constructor rounds float value to nearest int
+ assertEquals(167, col.getGreen());
+ assertEquals(180, col.getBlue());
+
+ /*
+ * value = min
+ */
+ col = ColorUtils
+ .getGraduatedColour(10f, 10f, minColour, 30f, maxColour);
+ assertEquals(minColour, col);
+
+ /*
+ * value = max
+ */
+ col = ColorUtils
+ .getGraduatedColour(30f, 10f, minColour, 30f, maxColour);
+ assertEquals(maxColour, col);
+
+ /*
+ * value < min
+ */
+ col = ColorUtils.getGraduatedColour(0f, 10f, minColour, 30f, maxColour);
+ assertEquals(minColour, col);
+
+ /*
+ * value > max
+ */
+ col = ColorUtils
+ .getGraduatedColour(40f, 10f, minColour, 30f,
+ maxColour);
+ assertEquals(maxColour, col);
+
+ /*
+ * min = max
+ */
+ col = ColorUtils
+ .getGraduatedColour(40f, 10f, minColour, 10f, maxColour);
+ assertEquals(minColour, col);
+ }
}
* AGCTU. Test is not case-sensitive and ignores gaps.
*/
@Test(groups = { "Functional" })
- public void testIsNucleotide()
+ public void testIsNucleotide_sequences()
{
SequenceI seq = new Sequence("eightypercent", "agctuAGCPV");
assertFalse(Comparison.isNucleotide(new SequenceI[] { seq }));
0.001f);
}
+ @Test(groups = { "Functional" })
+ public void testIsNucleotide()
+ {
+ assertTrue(Comparison.isNucleotide('a'));
+ assertTrue(Comparison.isNucleotide('A'));
+ assertTrue(Comparison.isNucleotide('c'));
+ assertTrue(Comparison.isNucleotide('C'));
+ assertTrue(Comparison.isNucleotide('g'));
+ assertTrue(Comparison.isNucleotide('G'));
+ assertTrue(Comparison.isNucleotide('t'));
+ assertTrue(Comparison.isNucleotide('T'));
+ assertTrue(Comparison.isNucleotide('u'));
+ assertTrue(Comparison.isNucleotide('U'));
+ assertFalse(Comparison.isNucleotide('-'));
+ assertFalse(Comparison.isNucleotide('P'));
+ }
+
/**
* Test the percentage identity calculation for two sequences
*/
assertEquals(87.5f, Comparison.PID(seq1, seq2, 0, length, false, true),
0.001f);
}
+
+ @Test(groups = { "Functional" })
+ public void testIsNucleotideSequence()
+ {
+ assertFalse(Comparison.isNucleotideSequence(null, true));
+ assertTrue(Comparison.isNucleotideSequence("", true));
+ assertTrue(Comparison.isNucleotideSequence("aAgGcCtTuU", true));
+ assertTrue(Comparison.isNucleotideSequence("aAgGcCtTuU", false));
+ assertFalse(Comparison.isNucleotideSequence("xAgGcCtTuU", false));
+ assertFalse(Comparison.isNucleotideSequence("aAgGcCtTuUx", false));
+ assertTrue(Comparison.isNucleotideSequence("a A-g.GcCtTuU", true));
+ assertFalse(Comparison.isNucleotideSequence("a A-g.GcCtTuU", false));
+ }
}
<string><![CDATA[664]]></string>
</property>
<property name="sourceName">
- <string><![CDATA[groovy-all-1.8.2.jar]]></string>
+ <string><![CDATA[groovy-all-2.4.6-indy.jar]]></string>
</property>
<property name="overrideUnixPermissions">
<boolean>false</boolean>
<boolean>true</boolean>
</property>
<property name="destinationName">
- <string><![CDATA[groovy-all-1.8.2.jar]]></string>
+ <string><![CDATA[groovy-all-2.4.6-indy.jar]]></string>
</property>
<property name="fileSize">
<long>6149494</long>