<commit_before>package dr.evomodelxml.tree;

import dr.evolution.colouring.TreeColouringProvider;
import dr.evolution.tree.*;
import dr.evomodel.tree.TreeLogger;
import dr.inference.loggers.LogFormatter;
import dr.inference.loggers.Loggable;
import dr.inference.loggers.TabDelimitedFormatter;
import dr.inference.model.Likelihood;
import dr.inference.model.Parameter;
import dr.inferencexml.loggers.LoggerParser;
import dr.xml.*;

import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * @author <NAME>
 * @author <NAME>
 */
public class TreeLoggerParser extends LoggerParser {

    public static final String LOG_TREE = "logTree";
    public static final String NEXUS_FORMAT = "nexusFormat";
    //    public static final String USING_RATES = "usingRates";
    public static final String BRANCH_LENGTHS = "branchLengths";
    public static final String TIME = "time";
    public static final String SUBSTITUTIONS = "substitutions";
    public static final String SORT_TRANSLATION_TABLE = "sortTranslationTable";
    public static final String MAP_NAMES = "mapNamesToNumbers";
    public static final String DECIMAL_PLACES = "dp";
    //    public static final String NORMALISE_MEAN_RATE_TO = "normaliseMeanRateTo";
    public static final String FILTER_TRAITS = "traitFilter";
    public static final String TREE_TRAIT = "trait";
    public static final String NAME = "name";
    public static final String TAG = "tag";

    public String getParserName() {
        return LOG_TREE;
    }

    protected void parseXMLParameters(XMLObject xo) throws XMLParseException
    {
        tree = (Tree) xo.getChild(Tree.class);

        title = xo.getAttribute(TITLE, "");

        nexusFormat = xo.getAttribute(NEXUS_FORMAT, false);

        sortTranslationTable = xo.getAttribute(SORT_TRANSLATION_TABLE, true);

        boolean substitutions = xo.getAttribute(BRANCH_LENGTHS, "").equals(SUBSTITUTIONS);

        List<TreeAttributeProvider> taps = new ArrayList<TreeAttributeProvider>();
        List<TreeTraitProvider> ttps = new ArrayList<TreeTraitProvider>();

        for (int i = 0; i < xo.getChildCount(); i++) {
            Object cxo = xo.getChild(i);

            // This needs to be refactored into using a TreeTrait if Colouring is resurrected...
//            if (cxo instanceof TreeColouringProvider) {
//                final TreeColouringProvider colouringProvider = (TreeColouringProvider) cxo;
//                baps.add(new BranchAttributeProvider() {
//
//                    public String getBranchAttributeLabel() {
//                        return "deme";
//                    }
//
//                    public String getAttributeForBranch(Tree tree, NodeRef node) {
//                        TreeColouring colouring = colouringProvider.getTreeColouring(tree);
//                        BranchColouring bcol = colouring.getBranchColouring(node);
//                        StringBuilder buffer = new StringBuilder();
//                        if (bcol != null) {
//                            buffer.append("{");
//                            buffer.append(bcol.getChildColour());
//                            for (int i = 1; i <= bcol.getNumEvents(); i++) {
//                                buffer.append(",");
//                                buffer.append(bcol.getBackwardTime(i));
//                                buffer.append(",");
//                                buffer.append(bcol.getBackwardColourAbove(i));
//                            }
//                            buffer.append("}");
//                        }
//                        return buffer.toString();
//                    }
//                });
//
//            } else

            if (cxo instanceof Likelihood) {
                final Likelihood likelihood = (Likelihood) cxo;
                taps.add(new TreeAttributeProvider() {

                    public String[] getTreeAttributeLabel() {
                        return new String[] {"lnP"};
                    }

                    public String[] getAttributeForTree(Tree tree) {
                        return new String[] {Double.toString(likelihood.getLogLikelihood())};
                    }
                });
            }

            if (cxo instanceof TreeAttributeProvider) {
                taps.add((TreeAttributeProvider) cxo);
            }
            if (cxo instanceof TreeTraitProvider) {
                if (xo.hasAttribute(FILTER_TRAITS)) {
                    String[] matches = ((String) xo.getAttribute(FILTER_TRAITS)).split("[\\s,]+");
                    TreeTraitProvider ttp = (TreeTraitProvider) cxo;
                    TreeTrait[] traits = ttp.getTreeTraits();
                    List<TreeTrait> filteredTraits = new ArrayList<TreeTrait>();
                    for (String match : matches) {
                        for (TreeTrait trait : traits) {
                            if (trait.getTraitName().contains(match)) {
                                filteredTraits.add(trait);
                            }
                        }
                    }
                    if (filteredTraits.size() > 0) {
                        ttps.add(new TreeTraitProvider.Helper(filteredTraits));
                    }

                } else {
                    // Add all of them
                    ttps.add((TreeTraitProvider) cxo);
                }
            }
            if (cxo instanceof XMLObject) {
                XMLObject xco = (XMLObject)cxo;
                if (xco.getName().equals(TREE_TRAIT)) {
                    String name = xco.getStringAttribute(NAME);
                    String tag = xco.getStringAttribute(TAG);
                    TreeTraitProvider ttp = (TreeTraitProvider)xco.getChild(TreeTraitProvider.class);
                    TreeTrait trait = ttp.getTreeTrait(name);

                    ttps.add(new TreeTraitProvider.Helper(tag, trait));
                }
            }
            // Without this next block, branch rates get ignored :-(
            // BranchRateModels are now TreeTraitProviders so this is not needed.
//            if (cxo instanceof TreeTrait) {
//                final TreeTrait trait = (TreeTrait)cxo;
//                TreeTraitProvider ttp = new TreeTraitProvider() {<commit_msg>Added ability to log a specific tree trait using a different tag. XML looks like this (will log the second branch rates as 'trait.rate' whereas the first one will use its default 'rate'):<commit_after>package dr.evomodelxml.tree;

import dr.evolution.colouring.TreeColouringProvider;
import dr.evolution.tree.*;
import dr.evomodel.tree.TreeLogger;
import dr.inference.loggers.LogFormatter;
import dr.inference.loggers.Loggable;
import dr.inference.loggers.TabDelimitedFormatter;
import dr.inference.model.Likelihood;
import dr.inference.model.Parameter;
import dr.inferencexml.loggers.LoggerParser;
import dr.xml.*;

import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * @author <NAME>
 * @author <NAME>
 */
public class TreeLoggerParser extends LoggerParser {

    public static final String LOG_TREE = "logTree";
    public static final String NEXUS_FORMAT = "nexusFormat";
    //    public static final String USING_RATES = "usingRates";
    public static final String BRANCH_LENGTHS = "branchLengths";
    public static final String TIME = "time";
    public static final String SUBSTITUTIONS = "substitutions";
    public static final String SORT_TRANSLATION_TABLE = "sortTranslationTable";
    public static final String MAP_NAMES = "mapNamesToNumbers";
    public static final String DECIMAL_PLACES = "dp";
    //    public static final String NORMALISE_MEAN_RATE_TO = "normaliseMeanRateTo";
    public static final String FILTER_TRAITS = "traitFilter";
    public static final String TREE_TRAIT = "trait";
    public static final String NAME = "name";
    public static final String TAG = "tag";

    public String getParserName() {
        return LOG_TREE;
    }

    protected void parseXMLParameters(XMLObject xo) throws XMLParseException
    {
        tree = (Tree) xo.getChild(Tree.class);

        title = xo.getAttribute(TITLE, "");

        nexusFormat = xo.getAttribute(NEXUS_FORMAT, false);

        sortTranslationTable = xo.getAttribute(SORT_TRANSLATION_TABLE, true);

        boolean substitutions = xo.getAttribute(BRANCH_LENGTHS, "").equals(SUBSTITUTIONS);

        List<TreeAttributeProvider> taps = new ArrayList<TreeAttributeProvider>();
        List<TreeTraitProvider> ttps = new ArrayList<TreeTraitProvider>();

        for (int i = 0; i < xo.getChildCount(); i++) {
            Object cxo = xo.getChild(i);

            // This needs to be refactored into using a TreeTrait if Colouring is resurrected...
//            if (cxo instanceof TreeColouringProvider) {
//                final TreeColouringProvider colouringProvider = (TreeColouringProvider) cxo;
//                baps.add(new BranchAttributeProvider() {
//
//                    public String getBranchAttributeLabel() {
//                        return "deme";
//                    }
//
//                    public String getAttributeForBranch(Tree tree, NodeRef node) {
//                        TreeColouring colouring = colouringProvider.getTreeColouring(tree);
//                        BranchColouring bcol = colouring.getBranchColouring(node);
//                        StringBuilder buffer = new StringBuilder();
//                        if (bcol != null) {
//                            buffer.append("{");
//                            buffer.append(bcol.getChildColour());
//                            for (int i = 1; i <= bcol.getNumEvents(); i++) {
//                                buffer.append(",");
//                                buffer.append(bcol.getBackwardTime(i));
//                                buffer.append(",");
//                                buffer.append(bcol.getBackwardColourAbove(i));
//                            }
//                            buffer.append("}");
//                        }
//                        return buffer.toString();
//                    }
//                });
//
//            } else

            if (cxo instanceof Likelihood) {
                final Likelihood likelihood = (Likelihood) cxo;
                taps.add(new TreeAttributeProvider() {

                    public String[] getTreeAttributeLabel() {
                        return new String[] {"lnP"};
                    }

                    public String[] getAttributeForTree(Tree tree) {
                        return new String[] {Double.toString(likelihood.getLogLikelihood())};
                    }
                });
            }

            if (cxo instanceof TreeAttributeProvider) {
                taps.add((TreeAttributeProvider) cxo);
            }
            if (cxo instanceof TreeTraitProvider) {
                if (xo.hasAttribute(FILTER_TRAITS)) {
                    String[] matches = ((String) xo.getAttribute(FILTER_TRAITS)).split("[\\s,]+");
                    TreeTraitProvider ttp = (TreeTraitProvider) cxo;
                    TreeTrait[] traits = ttp.getTreeTraits();
                    List<TreeTrait> filteredTraits = new ArrayList<TreeTrait>();
                    for (String match : matches) {
                        for (TreeTrait trait : traits) {
                            if (trait.getTraitName().contains(match)) {
                                filteredTraits.add(trait);
                            }
                        }
                    }
                    if (filteredTraits.size() > 0) {
                        ttps.add(new TreeTraitProvider.Helper(filteredTraits));
                    }

                } else {
                    // Add all of them
                    ttps.add((TreeTraitProvider) cxo);
                }
            }
            if (cxo instanceof XMLObject) {
                XMLObject xco = (XMLObject)cxo;
                if (xco.getName().equals(TREE_TRAIT)) {
                    TreeTraitProvider ttp = (TreeTraitProvider)xco.getChild(TreeTraitProvider.class);

                    String name = xco.getStringAttribute(NAME);
                    final TreeTrait trait = ttp.getTreeTrait(name);

                    final String tag = xco.getStringAttribute(TAG);

                    ttps.add(new TreeTraitProvider.Helper(tag, new TreeTrait() {

                        public String getTraitName() {
                            return tag;
                        }

                        public Intent getIntent() {
                            return trait.getIntent();
                        }

                        public Class getTraitClass() {
                            return trait.getTraitClass();
                        }

                        public Object getTrait(Tree tree, NodeRef node) {
                            return trait.getTrait(tree, node);
                        }

                        public String getTraitString(Tree tree, NodeRef node) {
                            return trait.getTraitString(tree, node);
                        }

                        public boolean getLoggable() {
                            return trait.getLoggable();
                        }
                    }));
                }
            }
            // Without this next block, branch rates get ignored :-(
            // BranchRateModels are now TreeTraitProviders so this is not needed.
//            if (cxo instanceof TreeTrait) {
//                final TreeTrait trait = (TreeTrait)cxo;
//                TreeTraitProvider ttp = new TreeTraitProvider() {
{'fraction_non_alphanumeric': 0.09533512844771123, 'fraction_numerical': 0.00043664944327195983, 'mean_word_length': 1.6150333016175071, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6193184', 'n_tokens_mistral': 3578, 'n_tokens_neox': 3378, 'n_words': 799}