ensure successive matches to a regex have distinct annotation name (indice suffix...
[jalview.git] / src / jalview / analysis / ParseProperties.java
1 package jalview.analysis;
2
3 import com.stevesoft.pat.Regex;
4
5 import jalview.datamodel.*;
6
7 public class ParseProperties
8 {
9   /**
10    * Methods for parsing free text properties on alignments and sequences.
11    * There are a number of ways we might want to do this:
12    * arbitrary regex. and an associated score name for the number that's extracted.
13    * Regex that provides both score and name.
14    * 
15    * We may also want to :
16    * - modify description to remove parsed numbers (this behaviour is dangerous since exporting the alignment would lose the original form then)
17    * - 
18    * 
19    */
20   /**
21    * The alignment being operated on
22    */
23   private AlignmentI al=null;
24   
25   /**
26    * initialise a new property parser
27    * @param al
28    */
29   public ParseProperties(AlignmentI al) {
30     this.al = al;
31   }
32
33   public int getScoresFromDescription(String ScoreName, String ScoreDescriptions, String regex, boolean repeat)
34   {
35     return getScoresFromDescription(new String[] { ScoreName }, new String[] { ScoreDescriptions}, regex, repeat);
36   }
37
38   public int getScoresFromDescription(String[] ScoreNames, String[] ScoreDescriptions, String regex, boolean repeat) 
39   {
40     return getScoresFromDescription(al.getSequencesArray(), ScoreNames, ScoreDescriptions, regex, repeat);
41   }
42   /**
43    * Extract scores for sequences by applying regex to description string.
44    * @param seqs seuqences to extract annotation from.
45    * @param ScoreNames labels for each numeric field in regex match
46    * @param ScoreDescriptions description for each numeric field in regex match
47    * @param regex Regular Expression string for passing to <code>new com.stevesoft.patt.Regex(regex)</code>
48    * @param repeat true means the regex will be applied multiple times along the description string of each sequence
49    * @return total number of sequences that matched the regex
50    */
51   public int getScoresFromDescription(SequenceI[] seqs, String[] ScoreNames, String[] ScoreDescriptions, String regex, boolean repeat) 
52   {
53     int count=0;
54     Regex pattern = new Regex(regex);
55     if (pattern.numSubs()>ScoreNames.length)
56     {
57       // Check that we have enough labels and descriptions for any parsed scores.
58       int onamelen = ScoreNames.length;
59       String[] tnames = new String[pattern.numSubs()+1];
60       System.arraycopy(ScoreNames, 0, tnames, 0, ScoreNames.length);
61       String base = tnames[ScoreNames.length-1];
62       ScoreNames = tnames;
63       String descrbase = ScoreDescriptions[onamelen-1];
64       if (descrbase == null)
65         descrbase = "Score parsed from ("+regex+")";
66       tnames = new String[pattern.numSubs()+1];
67       System.arraycopy(ScoreDescriptions, 0, tnames, 0, ScoreDescriptions.length);
68       ScoreDescriptions = tnames;
69       for (int i=onamelen; i<ScoreNames.length; i++)
70       {
71         ScoreNames[i] = base+"_"+i;
72         ScoreDescriptions[i] = descrbase+" (column "+i+")";
73       }
74     }
75     for (int i=0; i<seqs.length; i++)
76     {
77       String descr = seqs[i].getDescription();
78       if (descr==null)
79         continue;
80       int pos=0;
81       boolean added=false;
82       int reps=0;
83       while ((repeat || pos==0) && pattern.searchFrom(descr, pos))
84       {
85         pos = pattern.matchedTo();
86         for (int cols=0; cols<pattern.numSubs(); cols++)
87         {
88           String sstring = pattern.stringMatched(cols+1);
89           double score=Double.NaN;
90           try {
91             score = new Double(sstring).doubleValue();
92           }
93           catch (Exception e)
94           {
95             // don't try very hard to parse if regex was wrong.
96             continue;
97           }
98           // add score to sequence annotation.
99           AlignmentAnnotation an = new AlignmentAnnotation(ScoreNames[cols] +((reps>0) ? "_"+reps : ""), ScoreDescriptions[cols], null);
100           an.setScore(score);
101           System.out.println("Score: "+ScoreNames[cols]+"="+score); // DEBUG
102           an.setSequenceRef(seqs[i]);
103           seqs[i].addAlignmentAnnotation(an);
104           al.addAnnotation(an);
105           added=true;
106         }
107         reps++; // repeated matches
108       }
109       if (added)
110       {
111         count++;
112       }
113     }
114     return count; 
115   }
116   public static void main(String argv[]) {
117     SequenceI[] seqs = new SequenceI[] { new Sequence("sq1","THISISAPLACEHOLDER"),
118             new Sequence("sq2","THISISAPLACEHOLDER"),
119             new Sequence("sq3","THISISAPLACEHOLDER"),
120             new Sequence("sq4","THISISAPLACEHOLDER")};
121     seqs[0].setDescription("1 mydescription1");
122     seqs[1].setDescription("mydescription2");
123     seqs[2].setDescription("2. 0.1 mydescription3");
124     seqs[3].setDescription("3 0.01 mydescription4");
125     //seqs[4].setDescription("5 mydescription5");
126     Alignment al = new Alignment(seqs);
127     ParseProperties pp = new ParseProperties(al);
128     String regex = ".*([-0-9.+]+)";
129     System.out.println("Matched "+pp.getScoresFromDescription("my Score", "my Score Description",regex, true)+" for "+regex);
130     regex = ".*([-0-9.+]+).+([-0-9.+]+).*";
131     System.out.println("Matched "+pp.getScoresFromDescription("my Score", "my Score Description",regex, true)+" for "+regex);
132     System.out.println("Finished.");
133   }
134 }