3347800ffea99344ec5252b3d73b78dc41bb7578
[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 com.stevesoft.pat.Regex;
24
25 import jalview.datamodel.AlignmentAnnotation;
26 import jalview.datamodel.AlignmentI;
27 import jalview.datamodel.SequenceI;
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[]
61     { ScoreName }, new String[]
62     { ScoreDescriptions }, regex, repeat);
63   }
64
65   public int getScoresFromDescription(String[] ScoreNames,
66           String[] ScoreDescriptions, String regex, boolean repeat)
67   {
68     return getScoresFromDescription(al.getSequencesArray(), ScoreNames,
69             ScoreDescriptions, regex, repeat);
70   }
71
72   /**
73    * Extract scores for sequences by applying regex to description string.
74    * 
75    * @param seqs
76    *          seuqences to extract annotation from.
77    * @param ScoreNames
78    *          labels for each numeric field in regex match
79    * @param ScoreDescriptions
80    *          description for each numeric field in regex match
81    * @param regex
82    *          Regular Expression string for passing to
83    *          <code>new com.stevesoft.patt.Regex(regex)</code>
84    * @param repeat
85    *          true means the regex will be applied multiple times along the
86    *          description string of each sequence
87    * @return total number of sequences that matched the regex
88    */
89   public int getScoresFromDescription(SequenceI[] seqs,
90           String[] ScoreNames, String[] ScoreDescriptions, String regex,
91           boolean repeat)
92   {
93     int count = 0;
94     Regex pattern = new Regex(regex);
95     if (pattern.numSubs() > ScoreNames.length)
96     {
97       // Check that we have enough labels and descriptions for any parsed
98       // scores.
99       int onamelen = ScoreNames.length;
100       String[] tnames = new String[pattern.numSubs() + 1];
101       System.arraycopy(ScoreNames, 0, tnames, 0, ScoreNames.length);
102       String base = tnames[ScoreNames.length - 1];
103       ScoreNames = tnames;
104       String descrbase = ScoreDescriptions[onamelen - 1];
105       if (descrbase == null)
106       {
107         descrbase = "Score parsed from (" + regex + ")";
108       }
109       tnames = new String[pattern.numSubs() + 1];
110       System.arraycopy(ScoreDescriptions, 0, tnames, 0,
111               ScoreDescriptions.length);
112       ScoreDescriptions = tnames;
113       for (int i = onamelen; i < ScoreNames.length; i++)
114       {
115         ScoreNames[i] = base + "_" + i;
116         ScoreDescriptions[i] = descrbase + " (column " + i + ")";
117       }
118     }
119     for (int i = 0; i < seqs.length; i++)
120     {
121       String descr = seqs[i].getDescription();
122       if (descr == null)
123       {
124         continue;
125       }
126       int pos = 0;
127       boolean added = false;
128       int reps = 0;
129       while ((repeat || pos == 0) && pattern.searchFrom(descr, pos))
130       {
131         pos = pattern.matchedTo();
132         for (int cols = 0; cols < pattern.numSubs(); cols++)
133         {
134           String sstring = pattern.stringMatched(cols + 1);
135           double score = Double.NaN;
136           try
137           {
138             score = new Double(sstring).doubleValue();
139           } catch (Exception e)
140           {
141             // don't try very hard to parse if regex was wrong.
142             continue;
143           }
144           // add score to sequence annotation.
145           AlignmentAnnotation an = new AlignmentAnnotation(ScoreNames[cols]
146                   + ((reps > 0) ? "_" + reps : ""),
147                   ScoreDescriptions[cols], null);
148           an.setScore(score);
149           System.out.println(seqs[i].getName() + " score: '"
150                   + ScoreNames[cols] + "' = " + score); // DEBUG
151           an.setSequenceRef(seqs[i]);
152           seqs[i].addAlignmentAnnotation(an);
153           al.addAnnotation(an);
154           added = true;
155         }
156         reps++; // repeated matches
157       }
158       if (added)
159       {
160         count++;
161       }
162     }
163     return count;
164   }
165 }