JAL-3210 Improvements to eclipse detection. New src tree and SwingJS updated from...
[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 import jalview.util.Platform;
27
28 import com.stevesoft.pat.Regex;
29
30 public class ParseProperties
31 {
32   /**
33    * Methods for parsing free text properties on alignments and sequences. There
34    * are a number of ways we might want to do this: arbitrary regex. and an
35    * associated score name for the number that's extracted. Regex that provides
36    * both score and name.
37    * 
38    * We may also want to : - modify description to remove parsed numbers (this
39    * behaviour is dangerous since exporting the alignment would lose the
40    * original form then) -
41    * 
42    */
43   /**
44    * The alignment being operated on
45    */
46   private AlignmentI al = null;
47
48   /**
49    * initialise a new property parser
50    * 
51    * @param al
52    */
53   public ParseProperties(AlignmentI al)
54   {
55     this.al = al;
56   }
57
58   public int getScoresFromDescription(String ScoreName,
59           String ScoreDescriptions, String regex, boolean repeat)
60   {
61     return getScoresFromDescription(new String[] { ScoreName },
62             new String[]
63             { ScoreDescriptions }, regex, repeat);
64   }
65
66   public int getScoresFromDescription(String[] ScoreNames,
67           String[] ScoreDescriptions, String regex, boolean repeat)
68   {
69     return getScoresFromDescription(al.getSequencesArray(), ScoreNames,
70             ScoreDescriptions, regex, repeat);
71   }
72
73   /**
74    * Extract scores for sequences by applying regex to description string.
75    * 
76    * @param seqs
77    *          seuqences to extract annotation from.
78    * @param ScoreNames
79    *          labels for each numeric field in regex match
80    * @param ScoreDescriptions
81    *          description for each numeric field in regex match
82    * @param regex
83    *          Regular Expression string for passing to
84    *          <code>new com.stevesoft.patt.Regex(regex)</code>
85    * @param repeat
86    *          true means the regex will be applied multiple times along the
87    *          description string of each sequence
88    * @return total number of sequences that matched the regex
89    */
90   public int getScoresFromDescription(SequenceI[] seqs, String[] ScoreNames,
91           String[] ScoreDescriptions, String regex, boolean repeat)
92   {
93     int count = 0;
94     Regex pattern = Platform.newRegex(regex, null);
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(
146                   ScoreNames[cols] + ((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 }