org.caleydo.view.domino.internal.data.Numerical1DMixin.java Source code

Java tutorial

Introduction

Here is the source code for org.caleydo.view.domino.internal.data.Numerical1DMixin.java

Source

/*******************************************************************************
 * Caleydo - Visualization for Molecular Biology - http://caleydo.org
 * Copyright (c) The Caleydo Team. All rights reserved.
 * Licensed under the new BSD license, available at http://caleydo.org/license
 *******************************************************************************/
package org.caleydo.view.domino.internal.data;

import java.util.Arrays;
import java.util.Collection;
import java.util.Set;

import org.caleydo.core.data.collection.EDimension;
import org.caleydo.core.data.collection.Histogram;
import org.caleydo.core.data.perspective.variable.Perspective;
import org.caleydo.core.util.color.Color;
import org.caleydo.core.util.function.IDoubleList;
import org.caleydo.core.util.function.MappedDoubleList;
import org.caleydo.core.view.opengl.layout2.manage.GLElementFactoryContext.Builder;
import org.caleydo.view.domino.api.model.EDirection;
import org.caleydo.view.domino.api.model.typed.ITypedCollection;
import org.caleydo.view.domino.api.model.typed.TypedGroupSet;
import org.caleydo.view.domino.api.model.typed.TypedList;
import org.caleydo.view.domino.api.model.typed.TypedSet;
import org.caleydo.view.domino.api.model.typed.TypedSetGroup;
import org.caleydo.view.domino.api.model.typed.util.BitSetSet;
import org.caleydo.view.domino.internal.Constants;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

/**
 * @author Samuel Gratzl
 *
 */
public class Numerical1DMixin {
    private final INumerical1DContainer c;
    private final int bins;
    private final int maxBinSize;
    private final float min, max;
    private final int size;

    private final Function<Integer, Double> toRaw = new Function<Integer, Double>() {
        @Override
        public Double apply(Integer input) {
            return c.getRaw(input.intValue()).doubleValue();
        }
    };

    public Numerical1DMixin(INumerical1DContainer c, TypedGroupSet groups, float min, float max) {
        this.c = c;
        this.bins = (int) Math.sqrt(groups.size());
        this.min = min;
        this.max = max;
        this.maxBinSize = createHist(groups).getLargestValue();
        this.size = groups.size();
    }

    public static TypedGroupSet extractGroups(Perspective p, INumerical1DContainer c) {
        Set<Integer> invalid = new BitSetSet();
        TypedSet d = TypedSet.of(p.getVirtualArray());
        for (Integer id : d) {
            float v = c.getNormalized(id);
            if (Float.isInfinite(v) || Float.isNaN(v))
                invalid.add(id);
        }
        if (invalid.isEmpty())
            return TypedGroupSet.createUngrouped(d);

        TypedSetGroup normal = new TypedSetGroup(
                new TypedSet(ImmutableSet.copyOf(Sets.difference(d, invalid)), d.getIdType()), "Normal",
                c.getColor());
        TypedSetGroup invalidG = new TypedSetGroup(new TypedSet(ImmutableSet.copyOf(invalid), d.getIdType()), "NaN",
                Color.NOT_A_NUMBER_COLOR);
        return new TypedGroupSet(normal, invalidG);
    }

    public Collection<String> getDefaultVisualization() {
        // FIXME hack
        if (c.getLabel().contains("Death"))
            return Arrays.asList("kaplanmeier", "boxandwhiskers", "heatmap");
        return Arrays.asList("axis", "boxandwhiskers", "kaplanmeier", "heatmap");
    }

    public Histogram createHist(ITypedCollection data) {
        Histogram h = new Histogram(bins);
        for (Integer id : data) {
            float v = c.getNormalized(id.intValue());
            if (Float.isNaN(v)) {
                h.addNAN(id);
            } else {
                int bucketIndex = toBin(v, bins);
                h.add(bucketIndex, id);
            }
        }
        return h;
    }

    public static int toBin(float v, int bins) {
        // this works because the values in the container are
        // already normalized
        int bucketIndex = (int) (v * bins);
        if (bucketIndex == bins)
            bucketIndex--;
        return bucketIndex;
    }

    static Color[] getHistColors(Histogram hist, TypedList data) {
        Color[] r = new Color[hist.size()];
        float f = 1.f / (r.length - 1);
        for (int i = 0; i < r.length; ++i) {
            r[i] = Constants.colorMapping(i * f);
        }
        return r;
    }

    static String[] getHistLabels(Histogram hist, TypedList data) {
        String[] r = new String[hist.size()];
        for (int i = 0; i < r.length; ++i) {
            r[i] = "Bin " + (i + 1);
        }
        return r;
    }

    public void fill(Builder b, TypedList data, EDimension dim, boolean[] existNeigbhor) {
        final Histogram hist = createHist(data);
        b.put(Histogram.class, hist);
        b.put("distribution.colors", getHistColors(hist, data));
        b.put("distribution.labels", getHistLabels(hist, data));
        b.put("distribution.largestBin", maxBinSize);
        b.put("distribution.total", size);

        b.put("id2double", toRaw);
        final MappedDoubleList<Integer> list = new MappedDoubleList<>(data, toRaw);
        b.put("min", min);
        b.put("max", max);
        b.put(IDoubleList.class, list);

        // FIXME hack, if we have positive and negatives to a centered bar plot
        if (min < 0 && max > 0)
            b.put("hbar.bar.center", 0);
        else {
            boolean leftN = existNeigbhor[EDirection.getPrimary(dim.opposite()).ordinal()];
            boolean rightN = existNeigbhor[EDirection.getPrimary(dim.opposite()).opposite().ordinal()];
            b.put("hbar.bar.left", (!rightN || (leftN && rightN)) && !(dim.isHorizontal() && !leftN && !rightN));
        }

        // b.put("hbar.id2color", new AlternatingColors(Color.BLACK, Color.LIGHT_GRAY, even(data)));
        b.put("hbar.id2color", Functions.constant(Color.BLACK));
        b.put("hbar.outline", Color.WHITE);
        // b.set("kaplanmeier.fillCurve");

        b.set("boxandwhiskers.showOutliers");
        b.set("boxandwhiskers.showMinMax");
        b.put("sheatmap.frameColor", Color.LIGHT_GRAY);

        if (dim.isVertical())
            b.set("axis.invertOrder");
    }

    /**
     * @param data
     * @return
     */
    private Set<Integer> even(TypedList data) {
        BitSetSet s = new BitSetSet();
        for (int i = 0; i < data.size(); i += 2)
            s.add(data.get(i));
        return s;
    }

    private static final class AlternatingColors implements Function<Integer, Color> {
        private final Color even, odd;
        private final Set<Integer> isEven;

        public AlternatingColors(Color even, Color odd, Set<Integer> isEven) {
            this.even = even;
            this.odd = odd;
            this.isEven = isEven;
        }

        @Override
        public Color apply(Integer input) {
            if (isEven.contains(input))
                return even;
            return odd;
        }
    }

}