001 package calhoun.analysis.crf.io;
002
003 import java.util.Collection;
004 import java.util.HashMap;
005 import java.util.Map;
006
007 import calhoun.util.Assert;
008
009 /** a composite input sequence made up of individual components. This is useful when putting together different
010 * features that may take different inputs. Each component is given a name within the overall composite and can
011 * be reference by that name. All sequences must have the same length. The value at any position in the sequence
012 * is a map that relates component names to their values at that position. */
013 public class InputSequenceComposite implements InputSequence<Map<String, Object>> {
014
015 Map<String, InputSequence<?>> components = new HashMap<String, InputSequence<?>>();
016 int length = -1;
017
018 /** default constructor. Components should be added with addComponents. */
019 public InputSequenceComposite() {
020 }
021
022 /** constructor that initializes the sequence with a set of components.
023 * @param data the initial input sequences to use as the components */
024 public InputSequenceComposite(Map<String, InputSequence<?>> data) {
025 addComponents(data);
026 }
027
028 /** adds a new component input sequence to this composite. Each new component must have a unique name and all
029 * components must have the same length. */
030 public void addComponent(String name, InputSequence<?> seq) {
031 Assert.a(!components.containsKey(name), "Component already exists in composite input: ", name);
032 if(length == -1) {
033 length = seq.length();
034 }
035 Assert.a(seq.length() == -1 || length == seq.length(), "Composite sequence has length ", length, " but attempted to add component named ", name, " of length ", seq.length());
036 components.put(name, seq);
037 }
038
039 /** adds all input sequences in the given map as components. */
040 public void addComponents(Map<String, InputSequence<?>> data) {
041 for(Map.Entry<String, InputSequence<?>> entry : data.entrySet()) {
042 addComponent(entry.getKey(), entry.getValue());
043 }
044 }
045
046 /** returns all of components of this input sequence.
047 * @return a map that maps component names to input sequences
048 */
049 public Map<String, InputSequence<?>> getComponents() {
050 return components;
051 }
052
053 public Map<String, Object> getX(int ix) {
054 Map<String, Object> ret = new HashMap<String, Object>();
055 for(Map.Entry<String, InputSequence<?>> entry : components.entrySet()) {
056 ret.put(entry.getKey(), entry.getValue().getX(ix));
057 }
058 return ret;
059 }
060
061 public int length() {
062 Assert.a(components.size() > 0, "Length of composite sequence was called before any components were added.");
063 return length;
064 }
065
066 public InputSequence<?> getComponent(String name) {
067 return components.get(name);
068 }
069
070 public Collection<String> listComponents() {
071 return components.keySet();
072 }
073
074 public InputSequenceComposite subSequence(int start, int end) {
075 Assert.a(start >= 1);
076 Assert.a(end <= length());
077 Assert.a(start <= end);
078
079 InputSequenceComposite ret = new InputSequenceComposite();
080 for(Map.Entry<String, InputSequence<?>> entry : components.entrySet()) {
081 ret.addComponent(entry.getKey(), entry.getValue().subSequence(start,end));
082 }
083
084 return ret;
085 }
086 }