/*
* BeagleSequenceSimulatorParser.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* 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.beagle.tools.parsers;
import dr.app.beagle.tools.BeagleSequenceSimulator;
import dr.app.beagle.tools.Partition;
import dr.evolution.alignment.Alignment;
import dr.evolution.alignment.SimpleAlignment;
import dr.evolution.datatype.Codons;
import dr.evolution.datatype.Nucleotides;
import dr.xml.*;
import java.util.ArrayList;
import java.util.logging.Logger;
/**
* @author Filip Bielejec
* @version $Id$
*/
public class BeagleSequenceSimulatorParser extends AbstractXMLObjectParser {
public static final String BEAGLE_SEQUENCE_SIMULATOR = "beagleSequenceSimulator";
public static final String PARALLEL = "parallel";
public static final String OUTPUT_ANCESTRAL_SEQUENCES = "outputAncestralSequences";
public static final String OUTPUT = "output";
public String getParserName() {
return BEAGLE_SEQUENCE_SIMULATOR;
}
@Override
public String getParserDescription() {
return "Beagle sequence simulator";
}
@Override
public Class<Alignment> getReturnType() {
return Alignment.class;
}
@Override
public XMLSyntaxRule[] getSyntaxRules() {
return new XMLSyntaxRule[]{
AttributeRule.newBooleanRule(PARALLEL, true, "Whether to use multiple Beagle instances for simulation, default is false (sequential execution)."),
new StringAttributeRule(OUTPUT, "Possible output formats",
SimpleAlignment.OutputType.values(), //TODO: this should ignore upper/lower cas
false),
new ElementRule(Partition.class, 1, Integer.MAX_VALUE)
};
}// END: getSyntaxRules
@Override
public Object parseXMLObject(XMLObject xo) throws XMLParseException {
String msg = "";
boolean parallel = false;
boolean outputAncestralSequences = false;
if (xo.hasAttribute(PARALLEL)) {
parallel = xo.getBooleanAttribute(PARALLEL);
}
if (xo.hasAttribute(OUTPUT_ANCESTRAL_SEQUENCES)) {
outputAncestralSequences = xo.getBooleanAttribute(OUTPUT_ANCESTRAL_SEQUENCES);
}
SimpleAlignment.OutputType output = SimpleAlignment.OutputType.FASTA;
if (xo.hasAttribute(OUTPUT)) {
output = SimpleAlignment.OutputType.parseFromString(
xo.getStringAttribute(OUTPUT));
}
int siteCount = 0;
int to = 0;
for (int i = 0; i < xo.getChildCount(); i++) {
Partition partition = (Partition) xo.getChild(i);
to = partition.to + 1;
if (to > siteCount) {
siteCount = to;
}
}// END: partitions loop
ArrayList<Partition> partitionsList = new ArrayList<Partition>();
for (int i = 0; i < xo.getChildCount(); i++) {
Partition partition = (Partition) xo.getChild(i);
if (partition.from > siteCount) {
throw new XMLParseException(
"Illegal 'from' attribute in " + PartitionParser.PARTITION + " element");
}
if (partition.to > siteCount) {
throw new XMLParseException(
"Illegal 'to' attribute in " + PartitionParser.PARTITION + " element");
}
if (partition.to == -1) {
partition.to = siteCount - 1;
}
if (partition.getRootSequence() != null) {
// TODO: what about 'every'?
int partitionSiteCount = (partition.to - partition.from) +1;
// System.out.println("SCRAAAAAM:" + partitionSiteCount);
if (partition.getRootSequence().getLength() != 3 * partitionSiteCount && partition.getFreqModel().getDataType() instanceof Codons) {
throw new RuntimeException("Root codon sequence " + "for partition "+ (i+1) +" has "
+ partition.getRootSequence().getLength() + " characters "
+ "expecting " + 3 * partitionSiteCount + " characters");
} else if (partition.getRootSequence().getLength() != partitionSiteCount && partition.getFreqModel().getDataType() instanceof Nucleotides) {
throw new RuntimeException("Root nuleotide sequence "+ "for partition "+ (i+1) +" has "
+ partition.getRootSequence().getLength() + " characters "
+ "expecting " + partitionSiteCount + " characters");
}// END: dataType check
// System.exit(-1);
}// END: ancestralSequence check
partitionsList.add(partition);
}// END: partitions loop
msg += "\n\t" + siteCount + ((siteCount > 1) ? " replications " : " replication");
if (msg.length() > 0) {
Logger.getLogger("dr.app.beagle.tools").info("Using Beagle Sequence Simulator: " + msg);
}
BeagleSequenceSimulator s = new BeagleSequenceSimulator(partitionsList);
SimpleAlignment alignment = s.simulate(parallel, outputAncestralSequences);
alignment.setOutputType(output);
return alignment;
}// END: parseXMLObject
}// END: class