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