/*
* CombinedTraces.java
*
* Copyright (C) 2002-2006 Alexei Drummond and Andrew Rambaut
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* BEAST 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.app.tracer.traces;
import dr.inference.trace.*;
import java.util.ArrayList;
import java.util.List;
/**
* A class for analysing multiple tracesets
*
* @author Andrew Rambaut
* @author Alexei Drummond
* @version $Id: CombinedTraces.java,v 1.3 2006/11/29 16:04:12 rambaut Exp $
*/
public class CombinedTraces extends FilteredTraceList { //implements TraceList {
public CombinedTraces(String name, LogFileTraces[] traceLists) throws TraceException {
if (traceLists == null || traceLists.length < 1) {
throw new TraceException("Must have at least 1 Traces object in a CombinedTraces");
}
this.name = name;
this.traceLists = new LogFileTraces[traceLists.length];
this.traceLists[0] = traceLists[0];
for (int i = 1; i < traceLists.length; i++) {
if (traceLists[i].getTraceCount() != traceLists[0].getTraceCount()) {
throw new TraceException("Cannot add to a CombinedTraces: the count of new traces do not match existing traces");
}
if (traceLists[i].getStepSize() != traceLists[0].getStepSize()) {
throw new TraceException("Cannot add to a CombinedTraces: the step sizes of the new traces do not match existing traces");
}
for (int j = 0; j < traceLists[0].getTraceCount(); j++) {
if (!traceLists[i].getTraceName(j).equals(traceLists[0].getTraceName(j))) {
throw new TraceException("Cannot add to a CombinedTraces: new traces do not match existing traces");
} else if (traceLists[i].getTrace(j).getTraceType() != traceLists[0].getTrace(j).getTraceType()) {
throw new TraceException("Cannot add to a CombinedTraces: new traces type do not match existing type");
}
}
this.traceLists[i] = traceLists[i];
}
}
/**
* @return the name of this trace list
*/
public String getName() {
return name;
}
/**
* @return the number of traces in this trace list
*/
public int getTraceCount() {
return traceLists[0].getTraceCount();
}
/**
* @return the index of the trace with the given name
*/
public int getTraceIndex(String name) {
return traceLists[0].getTraceIndex(name);
}
/**
* @return the name of the trace with the given index
*/
public String getTraceName(int index) {
return traceLists[0].getTraceName(index);
}
/**
* @return the number of states excluding the burnin
*/
public int getStateCount() {
int sum = 0;
for (LogFileTraces traceList : traceLists) {
sum += traceList.getStateCount();
}
return sum;
}
/**
* @return the number of states in the burnin
*/
public int getBurninStateCount() {
return 0;
}
public boolean isIncomplete() {
return false;
}
public int getBurnIn() {
return 0;
}
/**
* @return the size of the step between states
*/
public int getStepSize() {
return traceLists[0].getStepSize();
}
/**
* @return the last state in the chain
*/
public int getMaxState() {
return getStateCount() * getStepSize();
}
public List getValues(int index, int fromIndex, int toIndex) {
throw new UnsupportedOperationException("not available");
}
public List getValues(int index) {
List valuesList = new ArrayList();
for (LogFileTraces traceList : traceLists) {
valuesList.addAll(traceList.getValues(index));
}
return valuesList;
}
public List getBurninValues(int index) {
throw new UnsupportedOperationException("getBurninValues is not a valid operation on CombinedTracers");
}
/**
* @return the trace distribution statistic object for the given index
*/
public TraceDistribution getDistributionStatistics(int index) {
return getCorrelationStatistics(index);
}
/**
* @return the trace correlation statistic object for the given index
*/
public TraceCorrelation getCorrelationStatistics(int index) {
if (traceStatistics == null) {
return null;
// this can happen if the ESS has not been calculated yet.
// throw new RuntimeException("No ESS for combined traces? This is not supposed to happen.");
}
return traceStatistics[index];
}
public void analyseTrace(int index) {
// no offset: burnin is handled inside each TraceList we own and invisible to us.
if (traceStatistics == null) {
traceStatistics = new TraceCorrelation[getTraceCount()];
}
Trace trace = getTrace(index);
if (trace != null)
traceStatistics[index] = new TraceCorrelation(getValues(index), trace.getTraceType(), getStepSize());
}
public Trace getTrace(int index) {
for (LogFileTraces traceList : traceLists) {
if (traceList.getTrace(index).getTraceType() != traceLists[0].getTrace(index).getTraceType()) {
return null; // trace type not comparable
}
}
return traceLists[0].getTrace(index);
}
/**
* @return the number of trace lists that make up this combined
*/
public int getTraceListCount() {
return traceLists.length;
}
/**
* @param index the index of the trace
* @return the ith TreeTrace
*/
public TraceList getTraceList(int index) {
return traceLists[index];
}
//************************************************************************
// private methods
//************************************************************************
private LogFileTraces[] traceLists = null;
private TraceCorrelation[] traceStatistics = null;
private String name;
//************* Filter ******************
@Override
public boolean hasFilter(int traceIndex) {
return traceLists[0].hasFilter(traceIndex);
}
@Override
public void setFilter(int traceIndex, Filter filter) {
for (LogFileTraces traceList : traceLists) {
traceList.setFilter(traceIndex, filter);
}
this.refreshStatistics();
}
@Override
public Filter getFilter(int traceIndex) {
return traceLists[0].getFilter(traceIndex);
}
@Override
public void removeFilter(int traceIndex) {
for (LogFileTraces traceList : traceLists) {
traceList.removeFilter(traceIndex);
}
this.refreshStatistics();
}
@Override
public void removeAllFilters() {
for (LogFileTraces traceList : traceLists) {
traceList.removeAllFilters();
}
this.refreshStatistics();
}
@Override
protected void refreshStatistics() {
for (int i = 0; i < getTraceCount(); i++) {
analyseTrace(i);
}
}
}