StatsCalculator.java
001 package gate.creole.annic.lucene;
002 
003 import java.io.*;
004 import java.util.*;
005 import gate.creole.annic.Constants;
006 import gate.creole.annic.Hit;
007 import gate.creole.annic.Pattern;
008 import gate.creole.annic.PatternAnnotation;
009 import gate.creole.annic.SearchException;
010 import gate.creole.annic.apache.lucene.index.Term;
011 import gate.creole.annic.apache.lucene.search.*;
012 
013 public class StatsCalculator {
014 
015   /**
016    * Allows retriving frequencies for the given parameters. Please make
017    * sure that you close the searcher on your own. Failing to do so may
018    * result into many files being opened at the same time and that can
019    * cause the problem with your OS.
020    @throws SearchException
021    */
022   public static int freq(IndexSearcher searcher, String corpusToSearchIn,
023           String annotationSetToSearchIn, String annotationType,
024           String featureName, String valuethrows SearchException {
025 
026     try {
027       corpusToSearchIn = corpusToSearchIn == null
028               || corpusToSearchIn.trim().length() == 0
029               null
030               : corpusToSearchIn.trim();
031       annotationSetToSearchIn = annotationSetToSearchIn == null
032               || annotationSetToSearchIn.trim().length() == 0
033               null
034               : annotationSetToSearchIn.trim();
035       if(annotationType == null)
036         throw new SearchException("Annotation Type cannot be null");
037 
038       // term that contains a value to be searched in the index
039       Term term = null;
040       if(featureName == null && value == null) {
041         term = new Term("contents", annotationType, "*");
042       }
043       else if(featureName != null && value == null) {
044         term = new Term("contents", annotationType + "." + featureName, "**");
045       }
046       else if(featureName == null) {
047         throw new SearchException("FeatureName cannot be null");
048       }
049       else {
050         term = new Term("contents", value, annotationType + "." + featureName);
051       }
052 
053       // term query
054       TermQuery tq = new TermQuery(term);
055 
056       // indicates whether we want to use booleanQuery
057       boolean useBooleanQuery = false;
058       BooleanQuery bq = new BooleanQuery();
059 
060       if(corpusToSearchIn != null) {
061         PhraseQuery cq = new PhraseQuery();
062         cq.add(new Term(Constants.CORPUS_ID, corpusToSearchIn)new Integer(0),
063                 true);
064         bq.add(cq, true, false);
065         useBooleanQuery = true;
066       }
067 
068       if(annotationSetToSearchIn != null) {
069         PhraseQuery aq = new PhraseQuery();
070         aq.add(new Term(Constants.ANNOTATION_SET_ID, annotationSetToSearchIn),
071                 new Integer(0)true);
072         bq.add(aq, true, false);
073         useBooleanQuery = true;
074       }
075 
076       Hits corpusHits = null;
077       if(useBooleanQuery) {
078         bq.add(tq, true, false);
079         corpusHits = searcher.search(bq);
080       }
081       else {
082         corpusHits = searcher.search(tq);
083       }
084 
085       List<?>[] firstTermPositions = searcher.getFirstTermPositions();
086 
087       // if no result available, set null to our scores
088       if(firstTermPositions[0].size() == 0) {
089         return 0;
090       }
091 
092       int size = 0;
093       // iterate through each result and collect necessary
094       // information
095       for(int hitIndex = 0; hitIndex < corpusHits.length(); hitIndex++) {
096         int index = firstTermPositions[0].indexOf(new Integer(corpusHits
097                 .id(hitIndex)));
098 
099         // we fetch all the first term positions for the query
100         // issued
101         Integer freq = (Integer)firstTermPositions[4].get(index);
102         size += freq.intValue();
103       }
104       return size;
105     }
106     catch(IOException ioe) {
107       throw new SearchException(ioe);
108     }
109     finally {
110       searcher.initializeTermPositions();
111     }
112   }
113 
114   /**
115    @see #freq(IndexSearcher, String, String, String, String, String)
116    */
117   public static int freq(IndexSearcher searcher, String corpusToSearchIn,
118           String annotationSetToSearchIn, String annotationType)
119           throws SearchException {
120 
121     return freq(searcher, corpusToSearchIn, annotationSetToSearchIn,
122             annotationType, null, null);
123   }
124 
125   /**
126    @see #freq(IndexSearcher, String, String, String, String, String)
127    */
128   public static int freq(IndexSearcher searcher, String corpusToSearchIn,
129           String annotationSetToSearchIn, String annotationType,
130           String featureNamethrows SearchException {
131 
132     return freq(searcher, corpusToSearchIn, annotationSetToSearchIn,
133             annotationType, featureName, null);
134   }
135 
136   /**
137    * Allows retrieving frequencies for the given parameters.
138    @param value - set to null if only wants to retrieve frequencies for AT.feature
139    @param inMatchedSpan - true if only interested in frequencies from the matched spans.
140    @param inContext - true if only interested in frequencies from the contexts. Please note that both isMatchedSpan 
141    * and inContext can be set to true if interested in frequencies from the entire patterns, but cannot be set false
142    * at the same time.
143    @throws SearchException
144    */
145   public static int freq(List<Hit> patternsToSearchIn,
146           String annotationType, String feature, String value,
147           boolean inMatchedSpan, boolean inContextthrows SearchException {
148     if(patternsToSearchIn == null || patternsToSearchIn.isEmpty()) return 0;
149 
150     if(!inMatchedSpan && !inContext)
151       throw new SearchException(
152               "Both inMatchedSpan and inContext cannot be set to false");
153 
154     int count = 0;
155     for(Hit aResult1 : patternsToSearchIn) {
156       Pattern aResult = (PatternaResult1;
157       
158       List<PatternAnnotation> annots = new ArrayList<PatternAnnotation>();
159       if(inMatchedSpan && !inContext) {
160         annots = aResult.getPatternAnnotations(aResult.getStartOffset(),
161                 aResult.getEndOffset());
162       }
163       else if(!inMatchedSpan && inContext) {
164         annots = aResult.getPatternAnnotations(aResult
165                 .getLeftContextStartOffset(), aResult.getStartOffset());
166         annots.addAll(aResult.getPatternAnnotations(aResult.getEndOffset(),
167                 aResult.getRightContextEndOffset()));
168       }
169       else {
170         // both matchedSpan and context are set to true
171         annots = Arrays.asList(aResult.getPatternAnnotations());
172       }
173 
174       if(annots.isEmpty()) continue;
175       List<PatternAnnotation> subAnnots = null;
176       if(value == null) {
177         subAnnots = getPatternAnnotations(annots, annotationType, feature);
178       }
179       else {
180         subAnnots = getPatternAnnotations(annots, annotationType, feature,
181                 value);
182       }
183 
184       count += subAnnots.size();
185     }
186     return count;
187   }
188 
189   
190   /**
191    @see #freq(List, String, String, String, boolean, boolean)
192    */
193   public static int freq(List<Hit> patternsToSearchIn,
194           String annotationType, boolean inMatchedSpan, boolean inContextthrows SearchException {
195     if(patternsToSearchIn == null || patternsToSearchIn.isEmpty()) return 0;
196 
197     if(!inMatchedSpan && !inContext)
198       throw new SearchException(
199               "Both inMatchedSpan and inContext cannot be set to false");
200 
201     int count = 0;
202     for(Hit aResult1 : patternsToSearchIn) {
203       Pattern aResult = (PatternaResult1;
204 
205 
206       List<PatternAnnotation> annots = new ArrayList<PatternAnnotation>();
207       if(inMatchedSpan && !inContext) {
208         annots = aResult.getPatternAnnotations(aResult.getStartOffset(),
209                 aResult.getEndOffset());
210       }
211       else if(!inMatchedSpan && inContext) {
212         annots = aResult.getPatternAnnotations(aResult
213                 .getLeftContextStartOffset(), aResult.getStartOffset());
214         annots.addAll(aResult.getPatternAnnotations(aResult.getEndOffset(),
215                 aResult.getRightContextEndOffset()));
216       }
217       else {
218         // both matchedSpan and context are set to true
219         annots = Arrays.asList(aResult.getPatternAnnotations());
220       }
221 
222       if(annots.isEmpty()) continue;
223       List<PatternAnnotation> subAnnots = getPatternAnnotations(annots, annotationType);
224 
225       count += subAnnots.size();
226     }
227     return count;
228   }
229   
230   
231   /**
232    * Calculates frequencies for all possible values of the provided AT.feature
233    @param patternsToSearchIn
234    @param annotationType
235    @param feature
236    @param inMatchedSpan
237    @param inContext
238    @return returns a map where key is the unique value of AT.feature and value is the Integer object giving count for the value.
239    @throws SearchException
240    */
241   public static Map<String, Integer> freqForAllValues(
242           List<Hit> patternsToSearchIn, String annotationType,
243           String feature, boolean inMatchedSpan, boolean inContext)
244           throws SearchException {
245     Map<String, Integer> toReturn = new HashMap<String, Integer>();
246     if(patternsToSearchIn == null || patternsToSearchIn.isEmpty())
247       return toReturn;
248 
249     
250     if(!inMatchedSpan && !inContext)
251       throw new SearchException(
252               "Both inMatchedSpan and inContext cannot be set to false");
253 
254     for(Hit aResult1 : patternsToSearchIn) {
255       Pattern aResult = (PatternaResult1;
256 
257 
258       List<PatternAnnotation> annots = new ArrayList<PatternAnnotation>();
259       if(inMatchedSpan && !inContext) {
260         annots = aResult.getPatternAnnotations(aResult.getStartOffset(),
261                 aResult.getEndOffset());
262       }
263       else if(!inMatchedSpan && inContext) {
264         annots = aResult.getPatternAnnotations(aResult
265                 .getLeftContextStartOffset(), aResult.getStartOffset());
266         annots.addAll(aResult.getPatternAnnotations(aResult.getEndOffset(),
267                 aResult.getRightContextEndOffset()));
268       }
269       else {
270         // both matchedSpan and context are set to true
271         annots = Arrays.asList(aResult.getPatternAnnotations());
272       }
273 
274       if(annots.isEmpty()) continue;
275       List<PatternAnnotation> subAnnots = getPatternAnnotations(annots,
276               annotationType, feature);
277 
278       for(PatternAnnotation pa : subAnnots) {
279         String uniqueKey = pa.getFeatures().get(feature);
280         Integer counter = toReturn.get(uniqueKey);
281         if(counter == null) {
282           counter = new Integer(1);
283           toReturn.put(uniqueKey, counter);
284         }
285         else {
286           counter = new Integer(counter.intValue() 1);
287           toReturn.put(uniqueKey, counter);
288         }
289       }
290     }
291     return toReturn;
292   }
293 
294   private static List<PatternAnnotation> getPatternAnnotations(
295           List<PatternAnnotation> annotations, String type, String feature,
296           String value) {
297     List<PatternAnnotation> annots = new ArrayList<PatternAnnotation>();
298     for(int i = 0; i < annotations.size(); i++) {
299       PatternAnnotation ga1 = annotations.get(i);
300       if(ga1.getType().equals(type)) {
301         Map<String, String> features = ga1.getFeatures();
302         if(features != null && features.keySet().contains(feature)) {
303           if(features.get(feature).equals(value)) annots.add(ga1);
304         }
305       }
306     }
307     return annots;
308   }
309 
310   private static List<PatternAnnotation> getPatternAnnotations(
311           List<PatternAnnotation> annotations, String type, String feature) {
312     List<PatternAnnotation> annots = new ArrayList<PatternAnnotation>();
313     for(int i = 0; i < annotations.size(); i++) {
314       PatternAnnotation ga1 = annotations.get(i);
315       if(ga1.getType().equals(type)) {
316         Map<String, String> features = ga1.getFeatures();
317         if(features != null && features.keySet().contains(feature)) {
318           annots.add(ga1);
319         }
320       }
321     }
322     return annots;
323   }
324 
325   private static List<PatternAnnotation> getPatternAnnotations(
326           List<PatternAnnotation> annotations, String type) {
327     List<PatternAnnotation> annots = new ArrayList<PatternAnnotation>();
328     for(int i = 0; i < annotations.size(); i++) {
329       PatternAnnotation ga1 = annotations.get(i);
330       if(ga1.getType().equals(type)) {
331          annots.add(ga1);
332       }
333     }
334     return annots;
335   }
336   
337   
338 }