Skip to content
Snippets Groups Projects
Experiment.java 16.04 KiB
package eu.hbp.mip.model;

import ch.chuv.lren.mip.portal.WokenConversions;
import com.google.gson.*;
import com.google.gson.annotations.Expose;
import com.google.gson.reflect.TypeToken;
import ch.chuv.lren.woken.messages.datasets.DatasetId;
import ch.chuv.lren.woken.messages.query.ExperimentQuery;
import ch.chuv.lren.woken.messages.query.*;
import eu.hbp.mip.utils.TypesConvert;
import ch.chuv.lren.woken.messages.query.filters.FilterRule;
import ch.chuv.lren.woken.messages.variables.FeatureIdentifier;
import org.hibernate.annotations.Cascade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.Option;
import scala.collection.JavaConversions;

import javax.persistence.*;
import java.lang.reflect.Type;
import java.util.*;
import scala.Tuple2;

/**
 * Created by habfast on 21/04/16.
 */
@Entity
@Table(name = "`experiment`")
public class Experiment {

    public static final String WP_K_MEANS = "K_MEANS";
    public static final String WP_LINEAR_REGRESSION = "WP_LINEAR_REGRESSION";
    public static final String WP_VARIABLES_HISTOGRAM = "WP_VARIABLES_HISTOGRAM";
    public static final String WP_REGRESSION_TREE = "PIPELINE_ISOUP_REGRESSION_TREE_SERIALIZER";
    public static final String WP_MODEL_TREE = "PIPELINE_ISOUP_MODEL_TREE_SERIALIZER";

    private static final Logger LOGGER = LoggerFactory.getLogger(Experiment.class);

    private static final Gson gson = new Gson();

    @Id
    @Column(columnDefinition = "uuid")
    @org.hibernate.annotations.Type(type="pg-uuid")
    @Expose
    private UUID uuid;

    @Column(columnDefinition="TEXT")
    @Expose
    private String name;

    @Expose
    @ManyToOne
    @JoinColumn(name = "createdby_username")
    private User createdBy;

    @ManyToOne
    @Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
    @Expose
    private Model model;

    @Column(columnDefinition="TEXT")
    @Expose
    private String algorithms;

    @Column(columnDefinition="TEXT")
    @Expose
    private String validations;

    @Column(columnDefinition="TEXT")
    @Expose
    private String result;

    @Expose
    private Date created = new Date();

    @Expose
    private Date finished;

    @Expose
    private boolean hasError = false;

    @Expose
    private boolean hasServerError = false;

    @Expose
    private boolean shared = false;

    // whether or not the experiment's result have been resultsViewed by its owner
    @Expose
    private boolean resultsViewed = false;

    public Experiment() {
        /*
        *  Empty constructor is needed by Hibernate
        */
    }

    public ExperimentQuery prepareQuery(String user) {
        if (model == null || model.getQuery() == null)
            return new ExperimentQuery(null, null, null, null, null, Option.empty(), null, null, null, null, null, null);

        List<AlgorithmSpec> algorithms = new LinkedList<>();
        Type algoList = new TypeToken<LinkedList<eu.hbp.mip.model.Algorithm>>(){}.getType();
        List<eu.hbp.mip.model.Algorithm> algos = new Gson().fromJson(this.algorithms, algoList);
        for (eu.hbp.mip.model.Algorithm a: algos) {
            algorithms.add(new AlgorithmSpec(a.getCode(), TypesConvert.algoParamsToScala(a.getParameters()), Option.empty()));
        }

        List<ValidationSpec> validations = new LinkedList<>();
        Type validList = new TypeToken<LinkedList<eu.hbp.mip.model.ExperimentValidator>>(){}.getType();
        List<eu.hbp.mip.model.ExperimentValidator> valids = new Gson().fromJson(this.validations, validList);
        for (ExperimentValidator v: valids) {
            validations.add(new ValidationSpec(v.getCode(), TypesConvert.algoParamsToScala(v.getParameters())));
        }

        scala.collection.immutable.List<FeatureIdentifier> variablesSeq =
                TypesConvert.variablesToIdentifiers(model.getQuery().getVariables());
        scala.collection.immutable.List<FeatureIdentifier> covariablesSeq =
                TypesConvert.variablesToIdentifiers(model.getQuery().getCovariables());
        scala.collection.immutable.List<FeatureIdentifier> groupingSeq =
                TypesConvert.variablesToIdentifiers(model.getQuery().getGrouping());
        scala.collection.immutable.List<AlgorithmSpec> algorithmsSeq = JavaConversions.asScalaBuffer(algorithms).toList();
        scala.collection.immutable.List<ValidationSpec> validationsSeq = JavaConversions.asScalaBuffer(validations).toList();

        WokenConversions conv = new WokenConversions();
        scala.collection.immutable.Set<DatasetId> trainingDatasets = conv.toDatasets(model.getQuery().getTrainingDatasets());
        scala.collection.immutable.Set<DatasetId> testingDatasets = conv.toDatasets(model.getQuery().getTestingDatasets());
        scala.collection.immutable.Set<DatasetId> validationDatasets = conv.toDatasets(model.getQuery().getValidationDatasets());

        String filtersJson = model.getQuery().getFilters();
        Option<FilterRule> filters = conv.toFilterRule(filtersJson);
        UserId userId = new UserId(user);

        return new ExperimentQuery(userId, variablesSeq, covariablesSeq, groupingSeq, filters, Option.empty(),
                trainingDatasets, testingDatasets, algorithmsSeq, validationDatasets,
                validationsSeq, Option.empty());
    }

    private String chainsParams(List<String> params, String operator) {
        StringBuilder sb = new StringBuilder();
        int i = 0;
        for (String s : params)
        {
            i++;
            sb.append(s);
            if (i < params.size()) {
                sb.append(operator);
            }
        }
        return sb.toString();
    }

    public String computeExaremeQuery(List<AlgorithmParam> params) {
        List<ExaremeQueryElement> queryElements = new LinkedList<>();

        // parameters
        String design = ""; // TODO: don't assign to a global
        String nobuckets = "";

        if (params != null) {
            for (AlgorithmParam p : params)
            {
                ExaremeQueryElement paramEl = new ExaremeQueryElement();
                paramEl.setName(p.getCode());
                paramEl.setDesc("");
                paramEl.setValue(p.getValue());
                queryElements.add(paramEl);

                if (p.getCode().equals("design")) {
                    design = p.getValue();
                }

                if (p.getCode().equals("nobuckets")) {
                    nobuckets = p.getValue();
                }
            }
        }

        List<String> variables = new ArrayList<>();
        List<String> covariables = new ArrayList<>();
        List<String> groupings = new ArrayList<>();

        for (Variable var : model.getQuery().getVariables()) { variables.add(var.getCode()); }
        for (Variable var : model.getQuery().getCovariables()) { covariables.add(var.getCode()); }
        for (Variable var : model.getQuery().getGrouping()) { groupings.add(var.getCode()); }

        // Set algorithm specific queries
        String algoName = this.isExaremeAlgorithm()._2;
        if (algoName.equals(WP_K_MEANS)) {
            // columns
            List<String> columns = variables;
            columns.addAll(covariables);
            columns.addAll(groupings);

            ExaremeQueryElement columnsEl = new ExaremeQueryElement();
            columnsEl.setName("columns");
            columnsEl.setDesc("");
            columnsEl.setValue(chainsParams(columns, ","));
            queryElements.add(columnsEl);
        } else if (algoName.equals(WP_LINEAR_REGRESSION)) {
            List<String> nominals = covariables.isEmpty() ? groupings : covariables;
            nominals.addAll(groupings);

            String operator = design.equals("factorial") ? "*" : "+";

            ExaremeQueryElement xEl = new ExaremeQueryElement();
            xEl.setName("x");
            xEl.setDesc("");
            xEl.setValue(chainsParams(nominals, operator));
            queryElements.add(xEl);

            ExaremeQueryElement yEl = new ExaremeQueryElement();
            yEl.setName("y");
            yEl.setDesc("");
            yEl.setValue(chainsParams(variables, ","));
            queryElements.add(yEl);
        } else if (algoName.equals(WP_VARIABLES_HISTOGRAM)) {
            List<String> column1 = variables;
            ExaremeQueryElement columnsEl = new ExaremeQueryElement();
            columnsEl.setName("column1");
            columnsEl.setDesc("");
            columnsEl.setValue(chainsParams(column1, ","));
            queryElements.add(columnsEl);

            List<String> column2 = covariables.isEmpty() ? groupings : covariables;
            ExaremeQueryElement columnsEl2 = new ExaremeQueryElement();
            columnsEl2.setName("column2");
            columnsEl2.setDesc("");
            columnsEl2.setValue(chainsParams(column2, ","));
            queryElements.add(columnsEl2);

            if (!nobuckets.isEmpty()) {
                ExaremeQueryElement columnsEl3 = new ExaremeQueryElement();
                columnsEl3.setName("nobuckets");
                columnsEl3.setDesc("");
                columnsEl3.setValue(nobuckets);
                queryElements.add(columnsEl3);
            }
        } else if (algoName.equals(WP_REGRESSION_TREE) || algoName.equals(WP_MODEL_TREE)) {
            List<String> target = variables;
            List<String> descriptive = covariables.isEmpty() ? groupings : covariables;
            descriptive.addAll(groupings);

            ExaremeQueryElement xEl = new ExaremeQueryElement();
            xEl.setName("target_attributes");
            xEl.setDesc("");
            xEl.setValue(chainsParams(target, ","));
            queryElements.add(xEl);

            ExaremeQueryElement yEl = new ExaremeQueryElement();
            yEl.setName("descriptive_attributes");
            yEl.setDesc("");
            yEl.setValue(chainsParams(descriptive, ","));
            queryElements.add(yEl);
        }

        // datasets
        StringBuilder datasets = new StringBuilder();
        List<Variable> trainingDatasets = model.getQuery().getTrainingDatasets();
        int j = 0;
        for (Variable var : trainingDatasets)
        {
            j++;
            datasets.append(var.getCode());
            if (j < trainingDatasets.size() ) {
                datasets.append(",");
            }
        }

        ExaremeQueryElement datasetsEl = new ExaremeQueryElement();
        datasetsEl.setName("dataset");
        datasetsEl.setDesc("");
        // datasetsEl.setValue("adni,ppmi,edsd,fbf,clm");
        datasetsEl.setValue(datasets.toString());
        queryElements.add(datasetsEl);

        return gson.toJson(queryElements);
    }

    public JsonObject jsonify() {
        JsonObject exp = gson.toJsonTree(this).getAsJsonObject();
        JsonParser parser = new JsonParser();
        Tuple2<Boolean, String> isExaremeAlgorithm = this.isExaremeAlgorithm();

        if (this.algorithms != null)
        {
            exp.remove("algorithms");
            JsonArray jsonAlgorithms = parser.parse(this.algorithms).getAsJsonArray();
            exp.add("algorithms", jsonAlgorithms);
        }

        if (this.validations != null)
        {
            exp.remove("validations");
            JsonArray jsonValidations = parser.parse(this.validations).getAsJsonArray();
            exp.add("validations", jsonValidations);
        }

        if (this.result != null && !this.hasServerError) {
            exp.remove("result");

            if (!isExaremeAlgorithm._1) {
                JsonArray jsonResult = parser.parse(this.result).getAsJsonArray();
                exp.add("result", jsonResult);
            } else {
                JsonArray jsonArrayResult = new JsonArray();
                JsonObject jsonObjectResult = new JsonObject();

                JsonObject algoObject = parser.parse(this.algorithms).getAsJsonArray().get(0).getAsJsonObject();
                jsonObjectResult.add("algorithm", algoObject.get("name"));
                jsonObjectResult.add("code", algoObject.get("code"));

                exp.remove("result");
                JsonObject tryJson;
                try {
                    tryJson = parser.parse(this.result).getAsJsonArray().get(0).getAsJsonObject();
                } catch(JsonParseException e) {
                    tryJson = new JsonObject();
                    tryJson.add("result", new JsonPrimitive(this.result));
                }

                JsonObject jsonData = tryJson;
                jsonObjectResult.add("data", jsonData);

                // add mime-type
                String algo = isExaremeAlgorithm._2;
                if (jsonData.get("Error") != null) {
                    jsonObjectResult.add("type", new JsonPrimitive("text/plain+error"));
                } else if (algo.equals( WP_K_MEANS) || algo.equals( WP_VARIABLES_HISTOGRAM)) {
                    jsonObjectResult.add("type", new JsonPrimitive("application/vnd.highcharts+json"));
                } else if (algo.equals(WP_LINEAR_REGRESSION)) {
                    jsonObjectResult.add("type", new JsonPrimitive("application/vnd.dataresource+json"));
                } else if (algo.equals(WP_REGRESSION_TREE) || algo.equals(WP_MODEL_TREE)) {
                    jsonObjectResult.add("type", new JsonPrimitive("application/vnd.visjs+javascript"));
                }

                jsonArrayResult.add(jsonObjectResult);

                exp.add("result", jsonArrayResult);
            }
        }

        return exp;
    }

    public String getValidations() {
        return validations;
    }

    public void setValidations(String validations) {
        this.validations = validations;
    }

    public String getAlgorithms() {
        return algorithms;
    }

    public void setAlgorithms(String algorithms) {
        this.algorithms = algorithms;
    }

    public Model getModel() {
        return model;
    }

    public void setModel(Model model) {
        this.model = model;
    }

    public boolean isHasError() {
        return hasError;
    }

    public void setHasError(boolean hasError) {
        this.hasError = hasError;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public Date getFinished() {
        return finished;
    }

    public void setFinished(Date finished) {
        this.finished = finished;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public UUID getUuid() {
        return uuid;
    }

    public void setUuid(UUID uuid) {
        this.uuid = uuid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public User getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(User createdBy) {
        this.createdBy = createdBy;
    }

    public boolean isResultsViewed() {
        return resultsViewed;
    }

    public void setResultsViewed(boolean resultsViewed) {
        this.resultsViewed = resultsViewed;
    }

    public boolean isHasServerError() {
        return hasServerError;
    }

    public void setHasServerError(boolean hasServerError) {
        this.hasServerError = hasServerError;
    }

    public boolean isShared() {
        return shared;
    }

    public void setShared(boolean shared) {
        this.shared = shared;
    }

    public Tuple2<Boolean, String> isExaremeAlgorithm() {
        Boolean isExareme = false;
        String algorithm = "";

        String algorithms = this.algorithms;

        if (algorithms.contains(WP_K_MEANS)) {
            isExareme = true;
            algorithm = WP_K_MEANS;
        } else if (algorithms.contains(WP_LINEAR_REGRESSION)) {
            isExareme = true;
            algorithm = WP_LINEAR_REGRESSION;
        } else if (algorithms.contains(WP_VARIABLES_HISTOGRAM)) {
            isExareme = true;
            algorithm = WP_VARIABLES_HISTOGRAM;
        } else if (algorithms.contains(WP_REGRESSION_TREE)) {
            isExareme = true;
            algorithm = WP_REGRESSION_TREE;
        } else if (algorithms.contains(WP_MODEL_TREE)) {
            isExareme = true;
            algorithm = WP_MODEL_TREE;
        }

        return new Tuple2<Boolean, String>(isExareme, algorithm);
    }
}