View Javadoc

1   /*
2    * @(#)$Id: BatchProcess.java 689 2009-07-22 00:10:27Z bsigner $
3    *
4    * Author       :   Ueli Kurmann, igesture@uelikurmann.ch
5    *
6    * Purpose      : 	This class provides the logic of the batch process 
7    * 					for testing algorithm configurations.		
8    *	
9    * -----------------------------------------------------------------------
10   *
11   * Revision Information:
12   *
13   * Date             Who         Reason
14   *
15   * Dec 26, 2006     ukurmann    Initial Release
16   * Mar 20, 2007     bsigner     Cleanup
17   *
18   * -----------------------------------------------------------------------
19   *
20   * Copyright 1999-2009 ETH Zurich. All Rights Reserved.
21   *
22   * This software is the proprietary information of ETH Zurich.
23   * Use is subject to license terms.
24   * 
25   */
26  
27  
28  package org.ximtec.igesture.batch;
29  
30  import java.io.File;
31  import java.util.ArrayList;
32  import java.util.List;
33  import java.util.concurrent.Callable;
34  import java.util.logging.Level;
35  import java.util.logging.Logger;
36  
37  import org.sigtec.util.Constant;
38  import org.ximtec.igesture.algorithm.Algorithm;
39  import org.ximtec.igesture.algorithm.AlgorithmException;
40  import org.ximtec.igesture.algorithm.AlgorithmFactory;
41  import org.ximtec.igesture.batch.core.BatchAlgorithm;
42  import org.ximtec.igesture.batch.core.BatchForValue;
43  import org.ximtec.igesture.batch.core.BatchParameter;
44  import org.ximtec.igesture.batch.core.BatchPowerSetValue;
45  import org.ximtec.igesture.batch.core.BatchSequenceValue;
46  import org.ximtec.igesture.batch.core.BatchValue;
47  import org.ximtec.igesture.configuration.Configuration;
48  import org.ximtec.igesture.core.Gesture;
49  import org.ximtec.igesture.core.GestureSet;
50  import org.ximtec.igesture.core.ResultSet;
51  import org.ximtec.igesture.core.TestClass;
52  import org.ximtec.igesture.core.TestSet;
53  import org.ximtec.igesture.util.XMLTool;
54  
55  
56  /**
57   * This class provides the logic of the batch process for testing algorithm
58   * configurations.
59   * 
60   * @version 1.0 Dec 2006
61   * @author Ueli Kurmann, igesture@uelikurmann.ch
62   * @author Beat Signer, signer@inf.ethz.ch
63   */
64  public class BatchProcess implements Callable<BatchResultSet> {
65  
66     private static final Logger LOGGER = Logger.getLogger(AlgorithmFactory.class
67           .getName());
68  
69     private static final String NUMBER_CONFIGURATIONS = "Number of configurations: ";
70  
71     private BatchProcessContainer batchProcessContainer;
72  
73     private List<Configuration> configurations;
74  
75     TestSet testSet;
76  
77     List<GestureSet> sets;
78  
79  
80     /**
81      * Constructs a new batch process.
82      * 
83      * @param file the XML file with the configuration.
84      */
85     public BatchProcess(BatchProcessContainer container) {
86        this.batchProcessContainer = container;
87        this.configurations = createConfigurations(batchProcessContainer
88              .getAlgorithms());
89  
90        this.sets = batchProcessContainer.getGestureSets();
91     }
92  
93  
94     /**
95      * Adds a test set.
96      * 
97      * @param testSet the test set to be added.
98      */
99     public void setTestSet(TestSet testSet) {
100       this.testSet = testSet;
101    } // setTestSet
102 
103 
104    /**
105     * Adds a gesture set.
106     * 
107     * @param set the gesture set to be added.
108     */
109    public void addGestureSet(GestureSet set) {
110       this.sets.add(set);
111    } // addGestureSet
112 
113 
114    /**
115     * Adds a list of gesture sets.
116     * 
117     * @param sets the list of gesture sets to be added.
118     */
119    public void addGestureSets(List<GestureSet> sets) {
120       this.sets.addAll(sets);
121    } // addGestureSets
122 
123 
124    /**
125     * Runs the batch process.
126     * 
127     * @return the batch result set.
128     */
129    public BatchResultSet run() {
130       BatchResultSet batchResultSet = new BatchResultSet();
131       LOGGER.log(Level.INFO, NUMBER_CONFIGURATIONS + configurations.size());
132       int counter = 1;
133 
134       for (Configuration config : configurations) {
135          config.addGestureSets(sets);
136          BatchResult batchResult = new BatchResult(testSet, config);
137 
138          try {
139             batchResult.setStartTime();
140             Algorithm algorithm;
141             algorithm = AlgorithmFactory.createAlgorithm(config);
142 
143             for (TestClass testClass : testSet.getTestClasses()) {
144                 
145                for (Gesture<?> sample : testClass.getGestures()) {
146                   ResultSet resultSet = algorithm.recognise(sample);
147 
148                   if(Thread.currentThread().isInterrupted()){
149                      return null;
150                   }
151                   
152                   if (resultSet.isEmpty()) {
153 
154                      if (sample.getName().equals(TestSet.NOISE)) {
155                         batchResult.incRejectCorrect(sample.getName());
156                      }
157                      else {
158                         batchResult.incRejectError(sample.getName());
159                      }
160 
161                   }
162                   else {
163 
164                      if (resultSet.getResult().getGestureClassName().equals(
165                            sample.getName())) {
166                         batchResult.incCorrect(sample.getName());
167                      }
168                      else {
169                         batchResult.incError(sample.getName());
170                      }
171 
172                   }
173 
174                }
175             }
176 
177             batchResult.setEndTime();
178             batchResultSet.addResult(batchResult);
179          }
180          catch (final AlgorithmException e) {
181             LOGGER.log(Level.SEVERE, Constant.EMPTY_STRING, e);
182          }
183 
184          LOGGER.info((double)counter / configurations.size() * 100
185                + Constant.PERCENTAGE);
186          counter++;
187       }
188 
189       return batchResultSet;
190    } // run
191 
192 
193    /**
194     * Creates a list of configurations. This method permutes all possible
195     * parameters and creates configuration instances. For the permutation part a
196     * recursive method is invoked. For each permutation a configuration instance
197     * is created.
198     * 
199     * @param algorithms the BatchAlgorithm instances.
200     * @return a list of configurations.
201     */
202    public static List<Configuration> createConfigurations(
203          List<BatchAlgorithm> algorithms) {
204       final List<Configuration> result = new ArrayList<Configuration>();
205 
206       for (final BatchAlgorithm algorithm : algorithms) {
207          final Configuration config = new Configuration();
208          config.addAlgorithm(algorithm.getName());
209          permuteParameters(algorithm.getName(), algorithm.getParameters(), 0,
210                config, result);
211       }
212 
213       return result;
214    } // createConfigurations
215 
216 
217    /**
218     * Creates a list of configurations.
219     * 
220     * @param file the file containing the configurations.
221     * @return the newly created configurations.
222     */
223    public static List<Configuration> createConfigurations(File file) {
224       final BatchProcessContainer container = XMLTool
225             .importBatchProcessContainer(file);
226       final List<Configuration> configurations = createConfigurations(container
227             .getAlgorithms());
228 
229       // postprocess gesture sets
230       for (final Configuration config : configurations) {
231 
232          for (final GestureSet set : container.getGestureSets()) {
233             config.addGestureSet(set);
234          }
235 
236       }
237 
238       return configurations;
239    } // createConfigurations
240 
241 
242    /**
243     * A recursive method which iterates through all possible permutations.
244     * 
245     * @param algorithm the name of the algorithm.
246     * @param parameters the BatchParameter instance.
247     * @param index the index (position) of the parameter.
248     * @param configuration the current configuration.
249     * @param configurations the list of all generated configurations.
250     */
251    private static void permuteParameters(String algorithm,
252          List<BatchParameter> parameters, int index,
253          Configuration configuration, List<Configuration> configurations) {
254 
255       /**
256        * Abort Condition. The last parameter is reached so one configuration is
257        * complete and can be added to the list.
258        */
259       if (index == parameters.size()) {
260          configurations.add((Configuration)configuration.clone());
261          return;
262       }
263 
264       final BatchParameter param = parameters.get(index);
265       processSimpleParameter(param, configuration, algorithm, parameters, index,
266             configurations);
267       processPowerSetParameter(param, configuration, algorithm, parameters,
268             index, configurations);
269       processSequenceParameter(param, configuration, algorithm, parameters,
270             index, configurations);
271       processForLoopParameter(param, configuration, algorithm, parameters,
272             index, configurations);
273    } // permuteParameters
274 
275 
276    /**
277     * Processes simple value parameters.
278     * 
279     * @param param the batch parameter.
280     * @param configuration the configuration.
281     * @param algorithm the algorithm to be used.
282     * @param parameters the batch parameters to be used.
283     * @param index
284     */
285    protected static void processSimpleParameter(BatchParameter param,
286          Configuration configuration, String algorithm,
287          List<BatchParameter> parameters, int index,
288          List<Configuration> configurations) {
289 
290       if (param.getValue() != null) {
291          final BatchValue value = param.getValue();
292          final Configuration conf = (Configuration)configuration.clone();
293          conf.addParameter(algorithm, param.getName(), value.getValue());
294          permuteParameters(algorithm, parameters, index + 1, conf,
295                configurations);
296       }
297 
298    } // processSimpleParameter
299 
300 
301    /**
302     * Processes power set parameters.
303     * 
304     * @param param
305     * @param configuration
306     * @param algorithm
307     * @param parameters
308     * @param index
309     * @param configurations
310     */
311    protected static void processPowerSetParameter(BatchParameter param,
312          Configuration configuration, String algorithm,
313          List<BatchParameter> parameters, int index,
314          List<Configuration> configurations) {
315 
316       if (param.getPermutationValue() != null) {
317          final BatchPowerSetValue values = param.getPermutationValue();
318 
319          for (final String value : values.getValues()) {
320             final Configuration conf = (Configuration)configuration.clone();
321             conf.addParameter(algorithm, param.getName(), value);
322             permuteParameters(algorithm, parameters, index + 1, conf,
323                   configurations);
324          }
325 
326       }
327 
328    } // processPowerSetParameter
329 
330 
331    /**
332     * Processes sequence parameters.
333     * 
334     * @param param
335     * @param configuration
336     * @param algorithm
337     * @param parameters
338     * @param index
339     * @param configurations
340     */
341    protected static void processSequenceParameter(BatchParameter param,
342          Configuration configuration, String algorithm,
343          List<BatchParameter> parameters, int index,
344          List<Configuration> configurations) {
345 
346       if (param.getSequenceValue() != null) {
347          final BatchSequenceValue values = param.getSequenceValue();
348 
349          for (final String value : values.getValues()) {
350             final Configuration conf = (Configuration)configuration.clone();
351             conf.addParameter(algorithm, param.getName(), value);
352             permuteParameters(algorithm, parameters, index + 1, conf,
353                   configurations);
354          }
355 
356       }
357 
358    } // processPowerSetParameter
359 
360 
361    /**
362     * Processes for loop parameters.
363     * 
364     * @param param
365     * @param configuration
366     * @param algorithm
367     * @param parameters
368     * @param index
369     * @param configurations
370     */
371    protected static void processForLoopParameter(BatchParameter param,
372          Configuration configuration, String algorithm,
373          List<BatchParameter> parameters, int index,
374          List<Configuration> configurations) {
375 
376       if (param.getIncrementalValue() != null) {
377          final BatchForValue values = param.getIncrementalValue();
378 
379          for (final String value : values.getValues()) {
380             final Configuration conf = (Configuration)configuration.clone();
381             conf.addParameter(algorithm, param.getName(), value);
382             permuteParameters(algorithm, parameters, index + 1, conf,
383                   configurations);
384          }
385 
386       }
387 
388    } // processForLoopParameter
389 
390 
391    @Override
392    public BatchResultSet call() throws Exception {
393       return run();
394    }
395 
396 }