/*******************************************************************************
* Copyright (C) 2010-2012 Dominik Jain.
*
* This file is part of ProbCog.
*
* ProbCog is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ProbCog is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProbCog. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package probcog.hmm;
import java.util.Iterator;
import java.util.Vector;
import edu.tum.cs.util.datastruct.Map2List;
import edu.tum.cs.util.datastruct.MultiIterator;
/**
* @author Dominik Jain
*/
public class SegmentSequence<T> implements Iterable<Segment<T>> {
protected String name;
protected Vector<Segment<T>> seq = new Vector<Segment<T>>();
protected Map2List<Integer, Segment<T>> entriesByLabel = new Map2List<Integer, Segment<T>>();
/**
* for building
*/
int prevLabel = -1;
Segment<T> currentSegment = null;
public SegmentSequence(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void add(Segment<T> s) {
assert(s.label >= 0);
seq.add(s);
entriesByLabel.add(s.label, s);
}
public void deleteSegments(Integer label) {
for(Segment<?> s : entriesByLabel.remove(label))
seq.remove(s);
}
/**
* for stepwise building of the segment sequence; adds the frame to the sequence, starting a new segment if the label changed
* @param label the label of the frame
* @param item the frame to add
*/
public void build(int label, T item) {
assert(label >= 0);
if(label != prevLabel) {
currentSegment = new Segment<T>(label);
add(currentSegment);
}
currentSegment.add(item);
prevLabel = label;
}
/**
* manually ends the current segment, i.e. the next frame that is added with the build method will definitely be added to a new segment
*/
public void buildEndSegment() {
prevLabel = -1;
}
public Iterator<Segment<T>> iterator() {
return this.seq.iterator();
}
public Vector<Segment<T>> getSegments(int label) {
return entriesByLabel.get(label);
}
public Segment<T> get(int idx) {
return seq.get(idx);
}
public int size() {
return seq.size();
}
public Iterable<T> getDataPointSequence() {
MultiIterator<T> mi = new MultiIterator<T>();
for(Segment<T> s : seq)
mi.add(s);
return mi;
}
public Iterable<Integer> getLabelSequence() {
MultiIterator<Integer> mi = new MultiIterator<Integer>();
for(Segment<T> s : seq)
mi.add(s.getLabels());
return mi;
}
public int getNumDataPoints() {
int n = 0;
for(Segment<T> s : this.seq)
n += s.size();
return n;
}
public T getDataPoint(int index) {
Iterator<Segment<T>> iter = iterator();
while(iter.hasNext()) {
Segment<T> seg = iter.next();
if(index < seg.size())
return seg.get(index);
index -= seg.size();
}
throw new IllegalArgumentException("SegmentSequence has no element at index " + index);
}
public String toString() {
StringBuffer sb = new StringBuffer("SegmentSequence '" + name + "' [ ");
for(Segment<T> s: this.seq) {
sb.append(s.label);
sb.append(" ");
}
sb.append("]");
return sb.toString();
}
public SegmentSequence<T> filter(ISegmentSequenceFilter<T> filter) {
SegmentSequence<T> ret = new SegmentSequence<T>(this.name);
int i = 0;
for(Segment<T> seg : this) {
for(int j = 0; j < seg.size(); j++) {
T newItem = filter.apply(this, i++);
if(newItem == null)
continue;
ret.build(seg.label, newItem);
}
}
return ret;
}
}