JAL-2068 framework and example scripts for pluggable alignment
[jalview.git] / examples / groovy / featureCounter.groovy
1 import jalview.workers.FeatureCounterI;
2 import jalview.workers.AlignmentAnnotationFactory;
3
4 /*
5  * Example script that registers two alignment annotation calculators
6  * - one that counts residues in a column with Pfam annotation
7  * - one that counts only charged residues with Pfam annotation
8  * Modify this example as required to count by column any desired value that can be 
9  * derived from the residue and sequence features at each position of an alignment.
10  */
11
12 /*
13  * A closure that returns true for any Charged residue
14  */
15 def isCharged = { residue ->
16     switch(residue) {
17         case ['D', 'd', 'E', 'e', 'H', 'h', 'K', 'k', 'R', 'r']:
18             return true
19     }
20     false
21
22
23 /*
24  * A closure that returns 1 if sequence features include type 'Pfam', else 0
25  * Argument should be a list of SequenceFeature 
26  */
27 def hasPfam = { features -> 
28     for (sf in features)
29     {
30         /*
31          * Here we inspect the type of the sequence feature.
32          * You can also test sf.description, sf.score, sf.featureGroup,
33          * sf.strand, sf.phase, sf.begin, sf.end
34          * or sf.getValue(attributeName) for GFF 'column 9' properties
35          */
36         if ("Pfam".equals(sf.type))
37         {
38             return true
39         }
40     }
41     false
42 }
43
44 /*
45  * Closure that counts residues with a Pfam feature annotation
46  * Parameters are
47  * - the name (label) for the alignment annotation
48  * - the description (tooltip) for the annotation
49  * - a closure (groovy function) that tests whether to include a residue
50  * - a closure that tests whether to increment count based on sequence features  
51  */
52 def getColumnCounter = { name, desc, residueTester, featureCounter ->
53     [
54      getName: { name }, 
55      getDescription: { desc },
56      getMinColour: { [0, 255, 255] }, // cyan
57      getMaxColour: { [0, 0, 255] }, // blue
58      count: 
59          { res, feats -> 
60             def c = 0
61             if (residueTester.call(res))
62             {
63                 if (featureCounter.call(feats))
64                 {
65                     c++
66                 }
67             }
68             c
69          }
70      ] as FeatureCounterI
71 }
72
73 /*
74  * Define annotation that counts any residue with Pfam domain annotation
75  */
76 def pfamAnnotation = getColumnCounter("Pfam", "Count of residues with Pfam domain annotation", {true}, hasPfam)
77
78 /*
79  * Define annotation that counts charged residues with Pfam domain annotation
80  */
81 def chargedPfamAnnotation = getColumnCounter("Pfam charged", "Count of charged residues with Pfam domain annotation", isCharged, hasPfam)
82
83 /*
84  * Register the annotations
85  */
86 AlignmentAnnotationFactory.newCalculator(pfamAnnotation) 
87 AlignmentAnnotationFactory.newCalculator(chargedPfamAnnotation)