eb639b63a03108074f74a638f2ff8b71241bb6a9
[jalview.git] / src / jalview / analysis / ParseProperties.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.analysis;
22
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.AlignmentI;
25 import jalview.datamodel.SequenceI;
26
27 import com.stevesoft.pat.Regex;
28
29 public class ParseProperties
30 {
31   /**
32    * Methods for parsing free text properties on alignments and sequences. There
33    * are a number of ways we might want to do this: arbitrary regex. and an
34    * associated score name for the number that's extracted. Regex that provides
35    * both score and name.
36    * 
37    * We may also want to : - modify description to remove parsed numbers (this
38    * behaviour is dangerous since exporting the alignment would lose the
39    * original form then) -
40    * 
41    */
42   /**
43    * The alignment being operated on
44    */
45   private AlignmentI al = null;
46
47   /**
48    * initialise a new property parser
49    * 
50    * @param al
51    */
52   public ParseProperties(AlignmentI al)
53   {
54     this.al = al;
55   }
56
57   public int getScoresFromDescription(String ScoreName,
58           String ScoreDescriptions, String regex, boolean repeat)
59   {
60     return getScoresFromDescription(new String[] { ScoreName },
61             new String[] { ScoreDescriptions }, regex, repeat);
62   }
63
64   public int getScoresFromDescription(String[] ScoreNames,
65           String[] ScoreDescriptions, String regex, boolean repeat)
66   {
67     return getScoresFromDescription(al.getSequencesArray(), ScoreNames,
68             ScoreDescriptions, regex, repeat);
69   }
70
71   /**
72    * Extract scores for sequences by applying regex to description string.
73    * 
74    * @param seqs
75    *          seuqences to extract annotation from.
76    * @param ScoreNames
77    *          labels for each numeric field in regex match
78    * @param ScoreDescriptions
79    *          description for each numeric field in regex match
80    * @param regex
81    *          Regular Expression string for passing to
82    *          <code>new com.stevesoft.patt.Regex(regex)</code>
83    * @param repeat
84    *          true means the regex will be applied multiple times along the
85    *          description string of each sequence
86    * @return total number of sequences that matched the regex
87    */
88   public int getScoresFromDescription(SequenceI[] seqs,
89           String[] ScoreNames, String[] ScoreDescriptions, String regex,
90           boolean repeat)
91   {
92     int count = 0;
93     Regex pattern = new Regex(regex);
94     if (pattern.numSubs() > ScoreNames.length)
95     {
96       // Check that we have enough labels and descriptions for any parsed
97       // scores.
98       int onamelen = ScoreNames.length;
99       String[] tnames = new String[pattern.numSubs() + 1];
100       System.arraycopy(ScoreNames, 0, tnames, 0, ScoreNames.length);
101       String base = tnames[ScoreNames.length - 1];
102       ScoreNames = tnames;
103       String descrbase = ScoreDescriptions[onamelen - 1];
104       if (descrbase == null)
105       {
106         descrbase = "Score parsed from (" + regex + ")";
107       }
108       tnames = new String[pattern.numSubs() + 1];
109       System.arraycopy(ScoreDescriptions, 0, tnames, 0,
110               ScoreDescriptions.length);
111       ScoreDescriptions = tnames;
112       for (int i = onamelen; i < ScoreNames.length; i++)
113       {
114         ScoreNames[i] = base + "_" + i;
115         ScoreDescriptions[i] = descrbase + " (column " + i + ")";
116       }
117     }
118     for (int i = 0; i < seqs.length; i++)
119     {
120       String descr = seqs[i].getDescription();
121       if (descr == null)
122       {
123         continue;
124       }
125       int pos = 0;
126       boolean added = false;
127       int reps = 0;
128       while ((repeat || pos == 0) && pattern.searchFrom(descr, pos))
129       {
130         pos = pattern.matchedTo();
131         for (int cols = 0; cols < pattern.numSubs(); cols++)
132         {
133           String sstring = pattern.stringMatched(cols + 1);
134           double score = Double.NaN;
135           try
136           {
137             score = new Double(sstring).doubleValue();
138           } catch (Exception e)
139           {
140             // don't try very hard to parse if regex was wrong.
141             continue;
142           }
143           // add score to sequence annotation.
144           AlignmentAnnotation an = new AlignmentAnnotation(ScoreNames[cols]
145                   + ((reps > 0) ? "_" + reps : ""),
146                   ScoreDescriptions[cols], null);
147           an.setScore(score);
148           System.out.println(seqs[i].getName() + " score: '"
149                   + ScoreNames[cols] + "' = " + score); // DEBUG
150           an.setSequenceRef(seqs[i]);
151           seqs[i].addAlignmentAnnotation(an);
152           al.addAnnotation(an);
153           added = true;
154         }
155         reps++; // repeated matches
156       }
157       if (added)
158       {
159         count++;
160       }
161     }
162     return count;
163   }
164 }