Search in sources :

Example 31 with BEASTInterface

use of beast.core.BEASTInterface in project beast2 by CompEvol.

the class BeautiAlignmentProvider method addAlignments.

protected void addAlignments(BeautiDoc doc, List<BEASTInterface> selectedBEASTObjects) {
    for (BEASTInterface beastObject : selectedBEASTObjects) {
        if (beastObject instanceof Alignment) {
            // ensure ID of alignment is unique
            int k = 0;
            String id = beastObject.getID();
            boolean found = true;
            while (doc.pluginmap.containsKey(id) && found) {
                found = false;
                for (Alignment data : doc.alignments) {
                    if (data.getID().equals(beastObject.getID())) {
                        found = true;
                        break;
                    }
                }
                if (found) {
                    k++;
                    id = beastObject.getID() + k;
                } else {
                    BEASTInterface oldData = doc.pluginmap.get(beastObject.getID());
                    replaceItem(doc, oldData, beastObject);
                }
            }
            beastObject.setID(id);
            sortByTaxonName(((Alignment) beastObject).sequenceInput.get());
            if (getStartTemplate() != null) {
                doc.addAlignmentWithSubnet((Alignment) beastObject, getStartTemplate());
            }
        }
    }
}
Also used : FilteredAlignment(beast.evolution.alignment.FilteredAlignment) Alignment(beast.evolution.alignment.Alignment) BEASTInterface(beast.core.BEASTInterface)

Example 32 with BEASTInterface

use of beast.core.BEASTInterface in project beast2 by CompEvol.

the class BeautiAlignmentProvider method getAlignments.

/**
 * return new alignment given files
 * @param doc
 * @param files
 * @return
 */
public List<BEASTInterface> getAlignments(BeautiDoc doc, File[] files) {
    if (files == null) {
        // merge "+ button" and "drag drop" function
        return getAlignments(doc);
    }
    if (importers == null) {
        initImporters();
    }
    List<BEASTInterface> selectedBEASTObjects = new ArrayList<>();
    List<MRCAPrior> calibrations = new ArrayList<>();
    for (File file : files) {
        // create list of importers that can handle the file
        List<AlignmentImporter> availableImporters = new ArrayList<>();
        for (AlignmentImporter importer : importers) {
            if (importer.canHandleFile(file)) {
                availableImporters.add(importer);
            }
        }
        if (availableImporters.size() > 0) {
            AlignmentImporter importer = availableImporters.get(0);
            if (availableImporters.size() > 1) {
                // let user choose an importer
                List<String> descriptions = new ArrayList<>();
                for (AlignmentImporter i : availableImporters) {
                    descriptions.add(((BEASTInterface) i).getDescription());
                }
                String option = (String) JOptionPane.showInputDialog(null, "Which importer is appropriate", "Option", JOptionPane.WARNING_MESSAGE, null, descriptions.toArray(), descriptions.get(0));
                if (option == null) {
                    return selectedBEASTObjects;
                }
                int i = descriptions.indexOf(option);
                importer = availableImporters.get(i);
            }
            // get a fresh instance
            // try {
            // importer = importer.getClass().newInstance();
            // } catch (InstantiationException | IllegalAccessException e) {
            // // TODO Auto-generated catch block
            // e.printStackTrace();
            // }
            List<BEASTInterface> list = importer.loadFile(file);
            selectedBEASTObjects.addAll(list);
        } else {
            JOptionPane.showMessageDialog(null, "Unsupported sequence file.", "Error", JOptionPane.ERROR_MESSAGE);
        }
    }
    addAlignments(doc, selectedBEASTObjects);
    if (calibrations != null) {
        selectedBEASTObjects.addAll(calibrations);
    }
    // doc.addMRCAPriors(calibrations);
    return selectedBEASTObjects;
}
Also used : ArrayList(java.util.ArrayList) MRCAPrior(beast.math.distributions.MRCAPrior) BEASTInterface(beast.core.BEASTInterface) File(java.io.File)

Example 33 with BEASTInterface

use of beast.core.BEASTInterface in project beast2 by CompEvol.

the class AlignmentListInputEditor method updateModel.

/**
 * set partition of type columnNr to partition model nr rowNr *
 */
void updateModel(int columnNr, int rowNr) {
    Log.warning.println("updateModel: " + rowNr + " " + columnNr + " " + table.getSelectedRow() + " " + table.getSelectedColumn());
    for (int i = 0; i < partitionCount; i++) {
        Log.warning.println(i + " " + tableData[i][0] + " " + tableData[i][SITEMODEL_COLUMN] + " " + tableData[i][CLOCKMODEL_COLUMN] + " " + tableData[i][TREE_COLUMN]);
    }
    getDoc();
    String partition = (String) tableData[rowNr][columnNr];
    // check if partition needs renaming
    String oldName = null;
    boolean isRenaming = false;
    try {
        switch(columnNr) {
            case SITEMODEL_COLUMN:
                if (!doc.pluginmap.containsKey("SiteModel.s:" + partition)) {
                    String id = ((BEASTInterface) likelihoods[rowNr].siteModelInput.get()).getID();
                    oldName = BeautiDoc.parsePartition(id);
                    doc.renamePartition(BeautiDoc.SITEMODEL_PARTITION, oldName, partition);
                    isRenaming = true;
                }
                break;
            case CLOCKMODEL_COLUMN:
                {
                    String id = likelihoods[rowNr].branchRateModelInput.get().getID();
                    String clockModelName = id.substring(0, id.indexOf('.')) + ".c:" + partition;
                    if (!doc.pluginmap.containsKey(clockModelName)) {
                        oldName = BeautiDoc.parsePartition(id);
                        doc.renamePartition(BeautiDoc.CLOCKMODEL_PARTITION, oldName, partition);
                        isRenaming = true;
                    }
                }
                break;
            case TREE_COLUMN:
                if (!doc.pluginmap.containsKey("Tree.t:" + partition)) {
                    String id = likelihoods[rowNr].treeInput.get().getID();
                    oldName = BeautiDoc.parsePartition(id);
                    doc.renamePartition(BeautiDoc.TREEMODEL_PARTITION, oldName, partition);
                    isRenaming = true;
                }
                break;
        }
    } catch (Exception e) {
        JOptionPane.showMessageDialog(this, "Cannot rename item: " + e.getMessage());
        tableData[rowNr][columnNr] = oldName;
        return;
    }
    if (isRenaming) {
        doc.determinePartitions();
        initTableData();
        setUpComboBoxes();
        table.repaint();
        return;
    }
    int partitionID = BeautiDoc.ALIGNMENT_PARTITION;
    switch(columnNr) {
        case SITEMODEL_COLUMN:
            partitionID = BeautiDoc.SITEMODEL_PARTITION;
            break;
        case CLOCKMODEL_COLUMN:
            partitionID = BeautiDoc.CLOCKMODEL_PARTITION;
            break;
        case TREE_COLUMN:
            partitionID = BeautiDoc.TREEMODEL_PARTITION;
            break;
    }
    int partitionNr = doc.getPartitionNr(partition, partitionID);
    GenericTreeLikelihood treeLikelihood = null;
    if (partitionNr >= 0) {
        // we ar linking
        treeLikelihood = likelihoods[partitionNr];
    }
    // (TreeLikelihood) doc.pluginmap.get("treeLikelihood." +
    // tableData[rowNr][NAME_COLUMN]);
    boolean needsRePartition = false;
    PartitionContext oldContext = new PartitionContext(this.likelihoods[rowNr]);
    switch(columnNr) {
        case SITEMODEL_COLUMN:
            {
                SiteModelInterface siteModel = null;
                if (treeLikelihood != null) {
                    // getDoc().getPartitionNr(partition,
                    // BeautiDoc.SITEMODEL_PARTITION) !=
                    // rowNr) {
                    siteModel = treeLikelihood.siteModelInput.get();
                } else {
                    siteModel = (SiteModel) doc.pluginmap.get("SiteModel.s:" + partition);
                    if (siteModel != likelihoods[rowNr].siteModelInput.get()) {
                        PartitionContext context = getPartitionContext(rowNr);
                        try {
                            siteModel = (SiteModel.Base) BeautiDoc.deepCopyPlugin((BEASTInterface) likelihoods[rowNr].siteModelInput.get(), likelihoods[rowNr], (MCMC) doc.mcmc.get(), oldContext, context, doc, null);
                        } catch (RuntimeException e) {
                            JOptionPane.showMessageDialog(this, "Could not clone site model: " + e.getMessage());
                            return;
                        }
                    }
                }
                SiteModelInterface target = this.likelihoods[rowNr].siteModelInput.get();
                if (target instanceof SiteModel.Base && siteModel instanceof SiteModel.Base) {
                    if (!((SiteModel.Base) target).substModelInput.canSetValue(((SiteModel.Base) siteModel).substModelInput.get(), (SiteModel.Base) target)) {
                        throw new IllegalArgumentException("Cannot link site model: substitution models (" + ((SiteModel.Base) target).substModelInput.get().getClass().toString() + " and " + ((SiteModel.Base) siteModel).substModelInput.get().getClass().toString() + ") are incompatible");
                    }
                } else {
                    throw new IllegalArgumentException("Don't know how to link this site model");
                }
                needsRePartition = (this.likelihoods[rowNr].siteModelInput.get() != siteModel);
                this.likelihoods[rowNr].siteModelInput.setValue(siteModel, this.likelihoods[rowNr]);
                partition = ((BEASTInterface) likelihoods[rowNr].siteModelInput.get()).getID();
                partition = BeautiDoc.parsePartition(partition);
                getDoc().setCurrentPartition(BeautiDoc.SITEMODEL_PARTITION, rowNr, partition);
            }
            break;
        case CLOCKMODEL_COLUMN:
            {
                BranchRateModel clockModel = null;
                if (treeLikelihood != null) {
                    // getDoc().getPartitionNr(partition,
                    // BeautiDoc.CLOCKMODEL_PARTITION)
                    // != rowNr) {
                    clockModel = treeLikelihood.branchRateModelInput.get();
                } else {
                    clockModel = getDoc().getClockModel(partition);
                    if (clockModel != likelihoods[rowNr].branchRateModelInput.get()) {
                        PartitionContext context = getPartitionContext(rowNr);
                        try {
                            clockModel = (BranchRateModel) BeautiDoc.deepCopyPlugin(likelihoods[rowNr].branchRateModelInput.get(), likelihoods[rowNr], (MCMC) doc.mcmc.get(), oldContext, context, doc, null);
                        } catch (RuntimeException e) {
                            JOptionPane.showMessageDialog(this, "Could not clone clock model: " + e.getMessage());
                            return;
                        }
                    }
                }
                // make sure that *if* the clock model has a tree as input, it is
                // the same as
                // for the likelihood
                TreeInterface tree = null;
                for (Input<?> input : ((BEASTInterface) clockModel).listInputs()) {
                    if (input.getName().equals("tree")) {
                        tree = (TreeInterface) input.get();
                    }
                }
                if (tree != null && tree != this.likelihoods[rowNr].treeInput.get()) {
                    JOptionPane.showMessageDialog(this, "Cannot link clock model with different trees");
                    throw new IllegalArgumentException("Cannot link clock model with different trees");
                }
                needsRePartition = (this.likelihoods[rowNr].branchRateModelInput.get() != clockModel);
                this.likelihoods[rowNr].branchRateModelInput.setValue(clockModel, this.likelihoods[rowNr]);
                partition = likelihoods[rowNr].branchRateModelInput.get().getID();
                partition = BeautiDoc.parsePartition(partition);
                getDoc().setCurrentPartition(BeautiDoc.CLOCKMODEL_PARTITION, rowNr, partition);
            }
            break;
        case TREE_COLUMN:
            {
                TreeInterface tree = null;
                if (treeLikelihood != null) {
                    // getDoc().getPartitionNr(partition,
                    // BeautiDoc.TREEMODEL_PARTITION) !=
                    // rowNr) {
                    tree = treeLikelihood.treeInput.get();
                } else {
                    tree = (TreeInterface) doc.pluginmap.get("Tree.t:" + partition);
                    if (tree != likelihoods[rowNr].treeInput.get()) {
                        PartitionContext context = getPartitionContext(rowNr);
                        try {
                            tree = (TreeInterface) BeautiDoc.deepCopyPlugin((BEASTInterface) likelihoods[rowNr].treeInput.get(), likelihoods[rowNr], (MCMC) doc.mcmc.get(), oldContext, context, doc, null);
                        } catch (RuntimeException e) {
                            JOptionPane.showMessageDialog(this, "Could not clone tree model: " + e.getMessage());
                            return;
                        }
                        State state = ((MCMC) doc.mcmc.get()).startStateInput.get();
                        List<StateNode> stateNodes = new ArrayList<>();
                        stateNodes.addAll(state.stateNodeInput.get());
                        for (StateNode s : stateNodes) {
                            if (s.getID().endsWith(".t:" + oldContext.tree) && !(s instanceof TreeInterface)) {
                                try {
                                    @SuppressWarnings("unused") StateNode copy = (StateNode) BeautiDoc.deepCopyPlugin(s, likelihoods[rowNr], (MCMC) doc.mcmc.get(), oldContext, context, doc, null);
                                } catch (RuntimeException e) {
                                    JOptionPane.showMessageDialog(this, "Could not clone tree model: " + e.getMessage());
                                    return;
                                }
                            }
                        }
                    }
                }
                // sanity check: make sure taxon sets are compatible
                Taxon.assertSameTaxa(tree.getID(), tree.getTaxonset().getTaxaNames(), likelihoods[rowNr].dataInput.get().getID(), likelihoods[rowNr].dataInput.get().getTaxaNames());
                needsRePartition = (this.likelihoods[rowNr].treeInput.get() != tree);
                Log.warning.println("needsRePartition = " + needsRePartition);
                if (needsRePartition) {
                    TreeInterface oldTree = this.likelihoods[rowNr].treeInput.get();
                    List<TreeInterface> tModels = new ArrayList<>();
                    for (GenericTreeLikelihood likelihood : likelihoods) {
                        if (likelihood.treeInput.get() == oldTree) {
                            tModels.add(likelihood.treeInput.get());
                        }
                    }
                    if (tModels.size() == 1) {
                        // remove old tree from model
                        ((BEASTInterface) oldTree).setInputValue("estimate", false);
                        // use toArray to prevent ConcurrentModificationException
                        for (Object beastObject : BEASTInterface.getOutputs(oldTree).toArray()) {
                            // .toArray(new BEASTInterface[0])) {
                            for (Input<?> input : ((BEASTInterface) beastObject).listInputs()) {
                                try {
                                    if (input.get() == oldTree) {
                                        if (input.getRule() != Input.Validate.REQUIRED) {
                                            input.setValue(tree, /*null*/
                                            (BEASTInterface) beastObject);
                                        // } else {
                                        // input.setValue(tree, (BEASTInterface) beastObject);
                                        }
                                    } else if (input.get() instanceof List) {
                                        @SuppressWarnings("unchecked") List<TreeInterface> list = (List<TreeInterface>) input.get();
                                        if (list.contains(oldTree)) {
                                            // && input.getRule() != Validate.REQUIRED) {
                                            list.remove(oldTree);
                                            if (!list.contains(tree)) {
                                                list.add(tree);
                                            }
                                        }
                                    }
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
                likelihoods[rowNr].treeInput.setValue(tree, likelihoods[rowNr]);
                // TreeDistribution d = getDoc().getTreePrior(partition);
                // CompoundDistribution prior = (CompoundDistribution)
                // doc.pluginmap.get("prior");
                // if (!getDoc().posteriorPredecessors.contains(d)) {
                // prior.pDistributions.setValue(d, prior);
                // }
                partition = likelihoods[rowNr].treeInput.get().getID();
                partition = BeautiDoc.parsePartition(partition);
                getDoc().setCurrentPartition(BeautiDoc.TREEMODEL_PARTITION, rowNr, partition);
            }
    }
    tableData[rowNr][columnNr] = partition;
    if (needsRePartition) {
        List<BeautiSubTemplate> templates = new ArrayList<>();
        templates.add(doc.beautiConfig.partitionTemplate.get());
        templates.addAll(doc.beautiConfig.subTemplates);
        // keep applying rules till model does not change
        doc.setUpActivePlugins();
        int n;
        do {
            n = doc.posteriorPredecessors.size();
            doc.applyBeautiRules(templates, false, oldContext);
            doc.setUpActivePlugins();
        } while (n != doc.posteriorPredecessors.size());
        doc.determinePartitions();
    }
    if (treeLikelihood == null) {
        initTableData();
        setUpComboBoxes();
    }
    updateStatus();
}
Also used : MCMC(beast.core.MCMC) StateNode(beast.core.StateNode) ArrayList(java.util.ArrayList) Input(beast.core.Input) List(java.util.List) ArrayList(java.util.ArrayList) GenericTreeLikelihood(beast.evolution.likelihood.GenericTreeLikelihood) SiteModel(beast.evolution.sitemodel.SiteModel) TreeInterface(beast.evolution.tree.TreeInterface) BranchRateModel(beast.evolution.branchratemodel.BranchRateModel) State(beast.core.State) BEASTInterface(beast.core.BEASTInterface) EventObject(java.util.EventObject) SiteModelInterface(beast.evolution.sitemodel.SiteModelInterface)

Example 34 with BEASTInterface

use of beast.core.BEASTInterface in project beast2 by CompEvol.

the class AlignmentListInputEditor method delItem.

void delItem() {
    int[] selected = getTableRowSelection();
    if (selected.length == 0) {
        JOptionPane.showMessageDialog(this, "Select partitions to delete, before hitting the delete button");
    }
    // do the actual deleting
    for (int i = selected.length - 1; i >= 0; i--) {
        int rowNr = selected[i];
        // before deleting, unlink site model, clock model and tree
        // check whether any of the models are linked
        BranchRateModel.Base clockModel = likelihoods[rowNr].branchRateModelInput.get();
        SiteModelInterface siteModel = likelihoods[rowNr].siteModelInput.get();
        TreeInterface tree = likelihoods[rowNr].treeInput.get();
        List<GenericTreeLikelihood> cModels = new ArrayList<>();
        List<GenericTreeLikelihood> models = new ArrayList<>();
        List<GenericTreeLikelihood> tModels = new ArrayList<>();
        for (GenericTreeLikelihood likelihood : likelihoods) {
            if (likelihood != likelihoods[rowNr]) {
                if (likelihood.branchRateModelInput.get() == clockModel) {
                    cModels.add(likelihood);
                }
                if (likelihood.siteModelInput.get() == siteModel) {
                    models.add(likelihood);
                }
                if (likelihood.treeInput.get() == tree) {
                    tModels.add(likelihood);
                }
            }
        }
        try {
            if (cModels.size() > 0) {
                // clock model is linked, so we need to unlink
                if (doc.getPartitionNr(clockModel) != rowNr) {
                    tableData[rowNr][CLOCKMODEL_COLUMN] = getDoc().partitionNames.get(rowNr).partition;
                } else {
                    int freePartition = doc.getPartitionNr(cModels.get(0));
                    tableData[rowNr][CLOCKMODEL_COLUMN] = getDoc().partitionNames.get(freePartition).partition;
                }
                updateModel(CLOCKMODEL_COLUMN, rowNr);
            }
            if (models.size() > 0) {
                // site model is linked, so we need to unlink
                if (doc.getPartitionNr((BEASTInterface) siteModel) != rowNr) {
                    tableData[rowNr][SITEMODEL_COLUMN] = getDoc().partitionNames.get(rowNr).partition;
                } else {
                    int freePartition = doc.getPartitionNr(models.get(0));
                    tableData[rowNr][SITEMODEL_COLUMN] = getDoc().partitionNames.get(freePartition).partition;
                }
                updateModel(SITEMODEL_COLUMN, rowNr);
            }
            if (tModels.size() > 0) {
                // tree is linked, so we need to unlink
                if (doc.getPartitionNr((BEASTInterface) tree) != rowNr) {
                    tableData[rowNr][TREE_COLUMN] = getDoc().partitionNames.get(rowNr).partition;
                } else {
                    int freePartition = doc.getPartitionNr(tModels.get(0));
                    tableData[rowNr][TREE_COLUMN] = getDoc().partitionNames.get(freePartition).partition;
                }
                updateModel(TREE_COLUMN, rowNr);
            }
            getDoc().delAlignmentWithSubnet(alignments.get(rowNr));
            alignments.remove(rowNr);
            // remove deleted likelihood from likelihoods array
            GenericTreeLikelihood[] tmp = new GenericTreeLikelihood[likelihoods.length - 1];
            int k = 0;
            for (int j = 0; j < likelihoods.length; j++) {
                if (j != rowNr) {
                    tmp[k] = likelihoods[j];
                    k++;
                }
            }
            likelihoods = tmp;
            partitionCount--;
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "Deletion failed: " + e.getMessage());
            e.printStackTrace();
        }
    }
    MRCAPriorInputEditor.customConnector(doc);
    refreshPanel();
}
Also used : BranchRateModel(beast.evolution.branchratemodel.BranchRateModel) GenericTreeLikelihood(beast.evolution.likelihood.GenericTreeLikelihood) ArrayList(java.util.ArrayList) BEASTInterface(beast.core.BEASTInterface) SiteModelInterface(beast.evolution.sitemodel.SiteModelInterface) TreeInterface(beast.evolution.tree.TreeInterface)

Example 35 with BEASTInterface

use of beast.core.BEASTInterface in project beast2 by CompEvol.

the class AlignmentListInputEditor method replaceItem.

private void replaceItem(Alignment alignment) {
    BeautiAlignmentProvider provider = new BeautiAlignmentProvider();
    List<BEASTInterface> list = provider.getAlignments(doc);
    List<Alignment> alignments = new ArrayList<>();
    for (BEASTInterface o : list) {
        if (o instanceof Alignment) {
            alignments.add((Alignment) o);
        }
    }
    Alignment replacement = null;
    if (alignments.size() > 1) {
        JComboBox<Alignment> jcb = new JComboBox<Alignment>(alignments.toArray(new Alignment[] {}));
        JOptionPane.showMessageDialog(null, jcb, "Select a replacement alignment", JOptionPane.QUESTION_MESSAGE);
        replacement = (Alignment) jcb.getSelectedItem();
    } else if (alignments.size() == 1) {
        replacement = alignments.get(0);
    }
    if (replacement != null) {
        if (!replacement.getDataType().getClass().getName().equals(alignment.getDataType().getClass().getName())) {
            JOptionPane.showMessageDialog(null, "Data types do not match, so alignment cannot be replaced: " + replacement.getID() + " " + replacement.getDataType().getClass().getName() + " != " + alignment.getID() + " " + alignment.getDataType().getClass().getName());
            return;
        }
        // replace alignment
        Set<BEASTInterface> outputs = new LinkedHashSet<>();
        outputs.addAll(alignment.getOutputs());
        for (BEASTInterface o : outputs) {
            for (Input<?> input : o.listInputs()) {
                if (input.get() == alignment) {
                    input.setValue(replacement, o);
                    replacement.getOutputs().add(o);
                } else if (input.get() instanceof List) {
                    @SuppressWarnings("rawtypes") List inputlist = (List) input.get();
                    int i = inputlist.indexOf(alignment);
                    if (i >= 0) {
                        inputlist.set(i, replacement);
                        replacement.getOutputs().add(o);
                    }
                }
            }
        }
        int i = doc.alignments.indexOf(alignment);
        doc.alignments.set(i, replacement);
        refreshPanel();
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) JComboBox(javax.swing.JComboBox) ArrayList(java.util.ArrayList) FilteredAlignment(beast.evolution.alignment.FilteredAlignment) Alignment(beast.evolution.alignment.Alignment) BEASTInterface(beast.core.BEASTInterface) List(java.util.List) ArrayList(java.util.ArrayList)

Aggregations

BEASTInterface (beast.core.BEASTInterface)111 ArrayList (java.util.ArrayList)43 List (java.util.List)27 IOException (java.io.IOException)22 ParserConfigurationException (javax.xml.parsers.ParserConfigurationException)18 SAXException (org.xml.sax.SAXException)18 NodeList (org.w3c.dom.NodeList)13 Input (beast.core.Input)12 MRCAPrior (beast.math.distributions.MRCAPrior)12 File (java.io.File)12 InvocationTargetException (java.lang.reflect.InvocationTargetException)12 XMLParser (beast.util.XMLParser)11 TransformerException (javax.xml.transform.TransformerException)11 Alignment (beast.evolution.alignment.Alignment)10 XMLParserException (beast.util.XMLParserException)10 BEASTObject (beast.core.BEASTObject)9 Distribution (beast.core.Distribution)9 XMLProducer (beast.util.XMLProducer)9 CompoundDistribution (beast.core.util.CompoundDistribution)8 BranchRateModel (beast.evolution.branchratemodel.BranchRateModel)8