<commit_before>package beast.math.statistic;



import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.ArrayList;
import java.io.PrintStream;

import beast.core.*;
import beast.core.parameter.Parameter;


/**
 * A statistic based on evaluating simple expressions.
 * <p/>
 * The expressions are in RPN, so no parsing issues. whitespace separated. Variables (other statistics),
 * constants and operations. Currently just the basic four, but easy to extend.
 *
 * @author <NAME> in beast1, migrated to beast2 by <NAME>
 */
@Description("RPN calculator to evaluate simple expressions of parameters (Reverse Polish notation is a mathematical notation wherein every operator follows its operands)")
public class RPNcalculator extends CalculationNode implements Loggable, Function {


    public Input<String> strExpressionInput = new Input<String>("expression", "Expressions needed for the calculations", Input.Validate.REQUIRED);
    public Input<List<Parameter>> parametersInput = new Input<List<Parameter>>("parameter", "Parameters needed for the calculations", new ArrayList<Parameter>());

    private RPNexpressionCalculator[] expressions;
    private List<String> names;

    private Map variables;
    RPNexpressionCalculator.GetVariable[] vars;
    int dim;

    public void initAndValidate() throws Exception {

        names = new ArrayList<String>();
        dim = parametersInput.get().get(0).getDimension();

        int pdim;

        for (final Parameter p : parametersInput.get()) {

            pdim = p.getDimension();

            if (pdim != dim && dim != 1 && pdim != 1) {
                throw new Exception("error: all parameters have to have same length or be of dimension 1.");
            }
            if (pdim > dim) dim = pdim;

            expressions = new RPNexpressionCalculator[dim];
            names.add(p.toString());

            for (int i = 0; i < pdim; i++) {

                variables = new HashMap<String, Double[]>();

                variables.put(p.getID(), p.getValues());
            }
        }

        vars = new RPNexpressionCalculator.GetVariable[dim];

        for (int i = 0; i < dim; i++) {
            final int index = i;
            vars[i] = new RPNexpressionCalculator.GetVariable() {
                public double get(final String name) {
                    final Object[] values = ((Object[]) variables.get(name));
                    if (values[0] instanceof Boolean)
                        return ((Boolean) values[values.length > 1 ? index : 0] ? 1. : 0.);
                    if (values[0] instanceof Integer)
                        return (Integer) values[values.length > 1 ? index : 0];
                    return (Double) values[values.length > 1 ? index : 0];
                }
            };<commit_msg>closed #452 better error reporting for RPNCalculator<commit_after>package beast.math.statistic;



import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.ArrayList;
import java.io.PrintStream;

import beast.core.*;
import beast.core.parameter.Parameter;


/**
 * A statistic based on evaluating simple expressions.
 * <p/>
 * The expressions are in RPN, so no parsing issues. whitespace separated. Variables (other statistics),
 * constants and operations. Currently just the basic four, but easy to extend.
 *
 * @author <NAME> in beast1, migrated to beast2 by <NAME>
 */
@Description("RPN calculator to evaluate simple expressions of parameters (Reverse Polish notation is a mathematical notation wherein every operator follows its operands)")
public class RPNcalculator extends CalculationNode implements Loggable, Function {


    public Input<String> strExpressionInput = new Input<String>("expression", "Expressions needed for the calculations", Input.Validate.REQUIRED);
    public Input<List<Parameter>> parametersInput = new Input<List<Parameter>>("parameter", "Parameters needed for the calculations", new ArrayList<Parameter>());

    private RPNexpressionCalculator[] expressions;
    private List<String> names;

    private Map variables;
    RPNexpressionCalculator.GetVariable[] vars;
    int dim;

    public void initAndValidate() throws Exception {

        names = new ArrayList<String>();
        dim = parametersInput.get().get(0).getDimension();

        int pdim;

        for (final Parameter p : parametersInput.get()) {

            pdim = p.getDimension();

            if (pdim != dim && dim != 1 && pdim != 1) {
                throw new Exception("error: all parameters have to have same length or be of dimension 1.");
            }
            if (pdim > dim) dim = pdim;

            expressions = new RPNexpressionCalculator[dim];
            names.add(p.toString());

            for (int i = 0; i < pdim; i++) {

                variables = new HashMap<String, Double[]>();

                variables.put(p.getID(), p.getValues());
            }
        }

        vars = new RPNexpressionCalculator.GetVariable[dim];

        for (int i = 0; i < dim; i++) {
            final int index = i;
            vars[i] = new RPNexpressionCalculator.GetVariable() {
                public double get(final String name) {
                    final Object[] values = ((Object[]) variables.get(name));
                    if (values == null) {
                    	String ids = "";
                        for (final Parameter p : parametersInput.get()) {
                    		ids += p.getID() +", ";
                    	}
                    	if (parametersInput.get().size() > 0) {
                    		ids = ids.substring(0, ids.length() - 2);
                    	}
                    	throw new RuntimeException("Something went wront with the RPNCalculator with id=" + getID() +".\n"
                    			+ "There might be a typo on the expression.\n" +
                    			"It should only contain these: " + ids +"\n"
                    					+ "but contains " + name);
                    }
                    if (values[0] instanceof Boolean)
                        return ((Boolean) values[values.length > 1 ? index : 0] ? 1. : 0.);
                    if (values[0] instanceof Integer)
                        return (Integer) values[values.length > 1 ? index : 0];
                    return (Double) values[values.length > 1 ? index : 0];
                }
            };
{'fraction_non_alphanumeric': 0.10782772712983339, 'fraction_numerical': 0.006601697579377554, 'mean_word_length': 2.2201417004048585, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 38, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '6428948', 'n_tokens_mistral': 1694, 'n_tokens_neox': 1569, 'n_words': 539}