changeset 144:4065178f776b

Separate out plot into plot (big datasets, 3D) and chart (bar charts, other 2D stuff)
author Chris Cannam
date Sat, 27 Apr 2013 12:55:53 +0100
parents 476a03ca013b
children 3ffd7e25e3df
files yetilab/plot/chart.yeti yetilab/plot/plot.yeti yetilab/plot/test/test_plot.yeti
diffstat 3 files changed, 261 insertions(+), 249 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/yetilab/plot/chart.yeti	Sat Apr 27 12:55:53 2013 +0100
@@ -0,0 +1,258 @@
+module yetilab.plot.chart;
+
+import org.jzy3d.plot3d.text.drawable: DrawableTextBillboard, DrawableTextBitmap;
+import org.jzy3d.maths: Range, Coord3d;
+import org.jzy3d.plot3d.primitives: Shape, HistogramBar, FlatLine2d, Polygon, Quad, Point;
+import org.jzy3d.plot3d.primitives.axes.layout.providers: StaticTickProvider, RegularTickProvider;
+import org.jzy3d.plot3d.primitives.axes.layout.renderers: ITickRenderer, TickLabelMap, IntegerTickRenderer;
+import org.jzy3d.chart: Chart, ChartLauncher;
+import org.jzy3d.plot3d.builder: Builder;
+import org.jzy3d.colors: Color;
+import org.jzy3d.plot3d.rendering.canvas: Quality;
+import org.jzy3d.plot3d.rendering.view.modes: ViewPositionMode;
+
+import javax.imageio: ImageIO;
+
+import java.io: File;
+
+chartColours = array [
+    { r = 82,  g = 126, b = 154 }, // dark steel blue
+    { r = 161, g = 54,  b = 2   }, // red
+    { r = 207, g = 228, b = 148 }, // grey-green
+    { r = 21,  g = 183, b = 197 }, // light blue
+    { r = 251, g = 116, b = 43  }, // light red
+    { r = 200, g = 125, b = 234 }, // light purple
+    { r = 126, g = 33,  b = 28  }, // dried blood!
+    { r = 188, g = 13,  b = 207 }, // mid purple
+];    
+
+chartColour n =
+    if n < 0
+    then chartColour (-n)
+    else
+        rgb = chartColours[n % (length chartColours)];
+        new Color(rgb.r / 255.0, rgb.g / 255.0, rgb.b / 255.0);
+    fi;
+
+newPercentTickRenderer () =
+   (f v = " \(int (v * 100))%";
+    class PercentageTickRenderer extends ITickRenderer
+        String format(double value) f value,
+        String format(float value) f value
+    end;
+    new PercentageTickRenderer());
+
+newPaddedIntTickRenderer () =
+   (f v = "    \(int (v + 0.5))";
+    class PaddedIntTickRenderer extends ITickRenderer
+        String format(double value) f value,
+        String format(float value) f value
+    end;
+    new PaddedIntTickRenderer());
+
+parseOptions options defaultKeys defaultXKeys =
+   (parsed = {
+        var keys = array (sort defaultKeys),
+        var labels = [:],
+        var animated = false,
+        var normalised = false,
+        var unit = "",
+        var xkeys = array (sort defaultXKeys),
+        var saveTo = "",
+        var display = true,
+    };
+    for options
+       \case of
+        Keys kk: parsed.keys := array kk;
+        XKeys xk: parsed.xkeys := array xk;
+        Animated a: parsed.animated := a;
+        Normalised n: parsed.normalised := n;
+        Unit u: parsed.unit := u;
+        Labels ll: parsed.labels := ll;
+        SaveTo file: parsed.saveTo := file;
+        Display d: parsed.display := d;
+        esac;
+    if empty? parsed.labels then
+        parsed.labels := mapIntoHash id id parsed.keys
+    fi;
+    parsed);
+
+newChart opts =
+   (quality = Quality#Fastest;
+    quality#setAnimated(opts.animated);
+//    if opts.display then
+        new Chart(quality);
+//    else
+//        new Chart(quality, "offscreen,640,640");
+//    fi);
+    );
+
+showChart opts chart is 'a -> ~Chart -> () =
+   (if opts.display then
+        \() ChartLauncher#openChart(chart);
+    else
+        \() ChartLauncher#openStaticChart(chart);
+    fi;
+    if opts.saveTo != "" then
+        \() chart#screenshot(opts.saveTo);
+    fi);
+    
+plotBarChart options values =
+   (opts = parseOptions options (keys values) [];
+    chart = newChart opts;
+    var n = length opts.keys;
+    scene = chart#getScene();
+    ticks = new double[n];
+    tickLabels = new TickLabelMap();
+    var i = 0;
+    var x = n - i - 1;
+    total = sum (map do k: if k in values then values[k] else 0 fi done opts.keys);
+    for opts.keys do k:
+        bar = new HistogramBar();
+        v = if k in values then values[k] else 0 fi;
+        v = if opts.normalised and total > 0 then v / total else v fi;
+        bar#setData(new Coord3d(x, 0, 0), v, 0.45, chartColour i);
+        bar#setWireframeDisplayed(false);
+        scene#add(bar);
+        ticks[i] := i;
+        tickLabels#register(x, opts.labels[k]);
+        i := i + 1;
+        x := x - 1;
+    done;
+    chart#getView()#setViewPoint(new Coord3d(pi/2, 0, 0));
+    axes = chart#getAxeLayout();
+    axes#setXAxeLabelDisplayed(false);
+    axes#setYAxeLabelDisplayed(false);
+    axes#setZAxeLabelDisplayed(true);
+    if opts.normalised then
+        axes#setZAxeLabel("");
+        axes#setZTickRenderer(newPercentTickRenderer ());
+    else
+        axes#setZAxeLabel(opts.unit);
+    fi;
+    axes#setXTickProvider(new StaticTickProvider(ticks));
+    axes#setXTickRenderer(tickLabels);
+    axes#setYTickLabelDisplayed(false);
+    showChart opts chart);
+
+plotLines options values =
+   (opts = parseOptions options (keys values) (keys values[head (keys values)]);
+    chart = newChart opts;
+    scene = chart#getScene();
+    n = length opts.xkeys;
+    var z = 0;
+    for opts.keys do k:
+        v = values[k];
+        x = new float[n];
+        y = new float[n];
+        var i = 0;
+        for opts.xkeys do xk:
+            x[i] := i;
+            y[i] := if xk in v then v[xk] else 0 fi;
+            i := i + 1;
+        done;
+        line = new FlatLine2d(x, y, z);
+        line#setWireframeDisplayed(true);
+        line#setWireframeColor(chartColour z);
+        line#setWireframeWidth(2);
+        line#setFaceDisplayed(false);
+        scene#add(line);
+        z := z + 1;
+    done;
+    chart#getView()#setViewPoint(new Coord3d(0, 0, 0));
+    axes = chart#getAxeLayout();
+    axes#setXAxeLabelDisplayed(false);
+    axes#setYAxeLabelDisplayed(false);
+    axes#setZAxeLabelDisplayed(true);
+    axes#setZAxeLabel(opts.unit);
+    axes#setYTickLabelDisplayed(false);
+    showChart opts chart);
+
+stack keys xkeys values normalised =
+   (stacked = mapIntoHash id \(mapIntoHash id \{ y0 = 0, y1 = 0 } xkeys) keys;
+    prev = mapIntoHash id \0 xkeys;
+    valueOf k xk =
+        if k in values and xk in values[k] 
+        then values[k][xk] else 0 
+        fi;
+    for xkeys do xk:
+        total = sum (map do k: valueOf k xk done keys);
+        for keys do k:
+            value =
+                if normalised and total > 0
+                then (valueOf k xk) / total
+                else (valueOf k xk)
+                fi;
+            height = prev[xk] + value;
+            stacked[k][xk] := { y0 = prev[xk], y1 = height };
+            prev[xk] := height;
+        done;
+    done;
+    stacked);
+
+newRect x y0 y1 z colour is number -> number -> number -> number -> ~Color -> 'a =
+   (poly = new Quad();
+    poly#add(new Point(new Coord3d(x + 0.5, z, y0)));
+    poly#add(new Point(new Coord3d(x + 0.5, z, y1)));
+    poly#add(new Point(new Coord3d(x - 0.5, z, y1)));
+    poly#add(new Point(new Coord3d(x - 0.5, z, y0)));
+    poly#setWireframeDisplayed(true);
+    poly#setWireframeColor(colour);
+    poly#setFaceDisplayed(true);
+    poly#setColor(colour);
+    poly);
+
+plotStacked options values =
+   (opts = parseOptions options (keys values) (keys values[head (keys values)]);
+    chart = newChart opts;
+    scene = chart#getScene();
+    stacked = stack opts.keys opts.xkeys values opts.normalised;
+    var z = 0;
+    var ty = 0;
+    nxk = length opts.xkeys;
+    xticks = new double[nxk];
+    xtickLabels = new TickLabelMap();
+    for [0..nxk - 1] do x:
+        xticks[x] := x;
+        k = opts.xkeys[x];
+        xtickLabels#register(x, if k in opts.labels then opts.labels[k] else k fi);
+    done;
+    for opts.keys do k:
+        ranges = stacked[k];
+        c = chartColour z;
+        for [0..nxk - 1] do x:
+            xk = opts.xkeys[x];
+            rect = newRect x ranges[xk].y0 ranges[xk].y1 z c;
+            scene#add(rect);
+        done;
+        text = new DrawableTextBitmap(opts.labels[k], new Coord3d(-(nxk/5 + 0.5), z, ty), c);
+        scene#add(text);
+        z := z - 1;
+        ty := ty + 0.1;
+    done;
+    chart#getView()#setViewPoint(new Coord3d(-pi/2, 0, 0));
+    axes = chart#getAxeLayout();
+    axes#setXAxeLabelDisplayed(false);
+    if nxk < 10 then
+        axes#setXTickProvider(new StaticTickProvider(xticks));
+    fi;
+    axes#setXTickRenderer(xtickLabels);
+    axes#setYAxeLabelDisplayed(false);
+    axes#setZAxeLabelDisplayed(true);
+    if opts.normalised then 
+        axes#setZAxeLabel("");
+        axes#setZTickRenderer(newPercentTickRenderer ());
+    else
+        axes#setZAxeLabel(opts.unit);
+        axes#setZTickRenderer(newPaddedIntTickRenderer ());
+    fi;
+    axes#setYTickLabelDisplayed(false);
+    showChart opts chart);
+
+{
+    plotBarChart,
+    plotLines,
+    stack,
+    plotStacked,
+}
+
--- a/yetilab/plot/plot.yeti	Sat Apr 27 12:51:12 2013 +0100
+++ b/yetilab/plot/plot.yeti	Sat Apr 27 12:55:53 2013 +0100
@@ -1,11 +1,7 @@
 module yetilab.plot.plot;
 
 import org.jzy3d.plot3d.builder: Mapper;
-import org.jzy3d.plot3d.text.drawable: DrawableTextBillboard, DrawableTextBitmap;
 import org.jzy3d.maths: Range, Coord3d;
-import org.jzy3d.plot3d.primitives: Shape, HistogramBar, FlatLine2d, Polygon, Quad, Point;
-import org.jzy3d.plot3d.primitives.axes.layout.providers: StaticTickProvider, RegularTickProvider;
-import org.jzy3d.plot3d.primitives.axes.layout.renderers: ITickRenderer, TickLabelMap, IntegerTickRenderer;
 import org.jzy3d.chart: Chart, ChartLauncher;
 import org.jzy3d.plot3d.builder: Builder;
 import org.jzy3d.plot3d.builder.concrete: OrthonormalGrid;
@@ -14,29 +10,6 @@
 import org.jzy3d.plot3d.rendering.canvas: Quality;
 import org.jzy3d.plot3d.rendering.view.modes: ViewPositionMode;
 
-import javax.imageio: ImageIO;
-
-import java.io: File;
-
-chartColours = array [
-    { r = 82,  g = 126, b = 154 }, // dark steel blue
-    { r = 161, g = 54,  b = 2   }, // red
-    { r = 207, g = 228, b = 148 }, // grey-green
-    { r = 21,  g = 183, b = 197 }, // light blue
-    { r = 251, g = 116, b = 43  }, // light red
-    { r = 200, g = 125, b = 234 }, // light purple
-    { r = 126, g = 33,  b = 28  }, // dried blood!
-    { r = 188, g = 13,  b = 207 }, // mid purple
-];    
-
-chartColour n =
-    if n < 0
-    then chartColour (-n)
-    else
-        rgb = chartColours[n % (length chartColours)];
-        new Color(rgb.r / 255.0, rgb.g / 255.0, rgb.b / 255.0);
-    fi;
-
 newMatrixMapper matrix =
    (class MMapper extends Mapper
         double f(double x, double y)
@@ -60,69 +33,6 @@
     end;
     new FMapper());
 
-newPercentTickRenderer () =
-   (f v = " \(int (v * 100))%";
-    class PercentageTickRenderer extends ITickRenderer
-        String format(double value) f value,
-        String format(float value) f value
-    end;
-    new PercentageTickRenderer());
-
-newPaddedIntTickRenderer () =
-   (f v = "    \(int (v + 0.5))";
-    class PaddedIntTickRenderer extends ITickRenderer
-        String format(double value) f value,
-        String format(float value) f value
-    end;
-    new PaddedIntTickRenderer());
-
-parseOptions options defaultKeys defaultXKeys =
-   (parsed = {
-        var keys = array (sort defaultKeys),
-        var labels = [:],
-        var animated = false,
-        var normalised = false,
-        var unit = "",
-        var xkeys = array (sort defaultXKeys),
-        var saveTo = "",
-        var display = true,
-    };
-    for options
-       \case of
-        Keys kk: parsed.keys := array kk;
-        XKeys xk: parsed.xkeys := array xk;
-        Animated a: parsed.animated := a;
-        Normalised n: parsed.normalised := n;
-        Unit u: parsed.unit := u;
-        Labels ll: parsed.labels := ll;
-        SaveTo file: parsed.saveTo := file;
-        Display d: parsed.display := d;
-        esac;
-    if empty? parsed.labels then
-        parsed.labels := mapIntoHash id id parsed.keys
-    fi;
-    parsed);
-
-newChart opts =
-   (quality = Quality#Fastest;
-    quality#setAnimated(opts.animated);
-//    if opts.display then
-        new Chart(quality);
-//    else
-//        new Chart(quality, "offscreen,640,640");
-//    fi);
-    );
-
-showChart opts chart is 'a -> ~Chart -> () =
-   (if opts.display then
-        \() ChartLauncher#openChart(chart);
-    else
-        \() ChartLauncher#openStaticChart(chart);
-    fi;
-    if opts.saveTo != "" then
-        \() chart#screenshot(opts.saveTo);
-    fi);
-    
 plotMatrix matrix =
    (mapper = newMatrixMapper matrix;
     size = matrix.size;
@@ -141,158 +51,6 @@
     ChartLauncher#openChart(chart);
     ());
 
-plotBarChart options values =
-   (opts = parseOptions options (keys values) [];
-    chart = newChart opts;
-    var n = length opts.keys;
-    scene = chart#getScene();
-    ticks = new double[n];
-    tickLabels = new TickLabelMap();
-    var i = 0;
-    var x = n - i - 1;
-    total = sum (map do k: if k in values then values[k] else 0 fi done opts.keys);
-    for opts.keys do k:
-        bar = new HistogramBar();
-        v = if k in values then values[k] else 0 fi;
-        v = if opts.normalised and total > 0 then v / total else v fi;
-        bar#setData(new Coord3d(x, 0, 0), v, 0.45, chartColour i);
-        bar#setWireframeDisplayed(false);
-        scene#add(bar);
-        ticks[i] := i;
-        tickLabels#register(x, opts.labels[k]);
-        i := i + 1;
-        x := x - 1;
-    done;
-    chart#getView()#setViewPoint(new Coord3d(pi/2, 0, 0));
-    axes = chart#getAxeLayout();
-    axes#setXAxeLabelDisplayed(false);
-    axes#setYAxeLabelDisplayed(false);
-    axes#setZAxeLabelDisplayed(true);
-    if opts.normalised then
-        axes#setZAxeLabel("");
-        axes#setZTickRenderer(newPercentTickRenderer ());
-    else
-        axes#setZAxeLabel(opts.unit);
-    fi;
-    axes#setXTickProvider(new StaticTickProvider(ticks));
-    axes#setXTickRenderer(tickLabels);
-    axes#setYTickLabelDisplayed(false);
-    showChart opts chart);
-
-plotLines options values =
-   (opts = parseOptions options (keys values) (keys values[head (keys values)]);
-    chart = newChart opts;
-    scene = chart#getScene();
-    n = length opts.xkeys;
-    var z = 0;
-    for opts.keys do k:
-        v = values[k];
-        x = new float[n];
-        y = new float[n];
-        var i = 0;
-        for opts.xkeys do xk:
-            x[i] := i;
-            y[i] := if xk in v then v[xk] else 0 fi;
-            i := i + 1;
-        done;
-        line = new FlatLine2d(x, y, z);
-        line#setWireframeDisplayed(true);
-        line#setWireframeColor(chartColour z);
-        line#setWireframeWidth(2);
-        line#setFaceDisplayed(false);
-        scene#add(line);
-        z := z + 1;
-    done;
-    chart#getView()#setViewPoint(new Coord3d(0, 0, 0));
-    axes = chart#getAxeLayout();
-    axes#setXAxeLabelDisplayed(false);
-    axes#setYAxeLabelDisplayed(false);
-    axes#setZAxeLabelDisplayed(true);
-    axes#setZAxeLabel(opts.unit);
-    axes#setYTickLabelDisplayed(false);
-    showChart opts chart);
-
-stack keys xkeys values normalised =
-   (stacked = mapIntoHash id \(mapIntoHash id \{ y0 = 0, y1 = 0 } xkeys) keys;
-    prev = mapIntoHash id \0 xkeys;
-    valueOf k xk =
-        if k in values and xk in values[k] 
-        then values[k][xk] else 0 
-        fi;
-    for xkeys do xk:
-        total = sum (map do k: valueOf k xk done keys);
-        for keys do k:
-            value =
-                if normalised and total > 0
-                then (valueOf k xk) / total
-                else (valueOf k xk)
-                fi;
-            height = prev[xk] + value;
-            stacked[k][xk] := { y0 = prev[xk], y1 = height };
-            prev[xk] := height;
-        done;
-    done;
-    stacked);
-
-newRect x y0 y1 z colour is number -> number -> number -> number -> ~Color -> 'a =
-   (poly = new Quad();
-    poly#add(new Point(new Coord3d(x + 0.5, z, y0)));
-    poly#add(new Point(new Coord3d(x + 0.5, z, y1)));
-    poly#add(new Point(new Coord3d(x - 0.5, z, y1)));
-    poly#add(new Point(new Coord3d(x - 0.5, z, y0)));
-    poly#setWireframeDisplayed(true);
-    poly#setWireframeColor(colour);
-    poly#setFaceDisplayed(true);
-    poly#setColor(colour);
-    poly);
-
-plotStacked options values =
-   (opts = parseOptions options (keys values) (keys values[head (keys values)]);
-    chart = newChart opts;
-    scene = chart#getScene();
-    stacked = stack opts.keys opts.xkeys values opts.normalised;
-    var z = 0;
-    var ty = 0;
-    nxk = length opts.xkeys;
-    xticks = new double[nxk];
-    xtickLabels = new TickLabelMap();
-    for [0..nxk - 1] do x:
-        xticks[x] := x;
-        k = opts.xkeys[x];
-        xtickLabels#register(x, if k in opts.labels then opts.labels[k] else k fi);
-    done;
-    for opts.keys do k:
-        ranges = stacked[k];
-        c = chartColour z;
-        for [0..nxk - 1] do x:
-            xk = opts.xkeys[x];
-            rect = newRect x ranges[xk].y0 ranges[xk].y1 z c;
-            scene#add(rect);
-        done;
-        text = new DrawableTextBitmap(opts.labels[k], new Coord3d(-(nxk/5 + 0.5), z, ty), c);
-        scene#add(text);
-        z := z - 1;
-        ty := ty + 0.1;
-    done;
-    chart#getView()#setViewPoint(new Coord3d(-pi/2, 0, 0));
-    axes = chart#getAxeLayout();
-    axes#setXAxeLabelDisplayed(false);
-    if nxk < 10 then
-        axes#setXTickProvider(new StaticTickProvider(xticks));
-    fi;
-    axes#setXTickRenderer(xtickLabels);
-    axes#setYAxeLabelDisplayed(false);
-    axes#setZAxeLabelDisplayed(true);
-    if opts.normalised then 
-        axes#setZAxeLabel("");
-        axes#setZTickRenderer(newPercentTickRenderer ());
-    else
-        axes#setZAxeLabel(opts.unit);
-        axes#setZTickRenderer(newPaddedIntTickRenderer ());
-    fi;
-    axes#setYTickLabelDisplayed(false);
-    showChart opts chart);
-
 plotStructure structure =
     case structure of
     Grid matrix:
@@ -306,10 +64,6 @@
     newMatrixLogMapper,
     newMapper,
     plotMatrix, 
-    plotBarChart,
-    plotLines,
-    stack,
-    plotStacked,
     plotStructure,
 }
 
--- a/yetilab/plot/test/test_plot.yeti	Sat Apr 27 12:51:12 2013 +0100
+++ b/yetilab/plot/test/test_plot.yeti	Sat Apr 27 12:55:53 2013 +0100
@@ -1,6 +1,6 @@
 module yetilab.plot.test.test_plot;
 
-p = load yetilab.plot.plot;
+ch = load yetilab.plot.chart;
 
 { compare } = load yetilab.test.test;
 
@@ -8,7 +8,7 @@
 
 "stack": \(
     compare
-       (p.stack
+       (ch.stack
             [ "Conrad", "Alice", "Bob" ]
             [ "Jan", "Feb", "Mar" ]
             [ "Alice":  [ "Jan": 3, "Mar": 2 ],
@@ -28,7 +28,7 @@
 
 "stack-normalised": \(
     compare
-       (p.stack
+       (ch.stack
             [ "Conrad", "Alice", "Bob" ]
             [ "Jan", "Feb", "Mar" ]
             [ "Alice":  [ "Jan": 3, "Mar": 2 ],