annotate yetilab/plot/chart.yeti @ 210:3a2be6eb8bd3 matrix_opaque_immutable

Finish matrix api conversion compile fixes
author Chris Cannam
date Wed, 08 May 2013 21:10:29 +0100
parents 4065178f776b
children 4bce024b3cc6
rev   line source
Chris@144 1 module yetilab.plot.chart;
Chris@108 2
Chris@128 3 import org.jzy3d.plot3d.text.drawable: DrawableTextBillboard, DrawableTextBitmap;
Chris@119 4 import org.jzy3d.maths: Range, Coord3d;
Chris@126 5 import org.jzy3d.plot3d.primitives: Shape, HistogramBar, FlatLine2d, Polygon, Quad, Point;
Chris@138 6 import org.jzy3d.plot3d.primitives.axes.layout.providers: StaticTickProvider, RegularTickProvider;
Chris@140 7 import org.jzy3d.plot3d.primitives.axes.layout.renderers: ITickRenderer, TickLabelMap, IntegerTickRenderer;
Chris@108 8 import org.jzy3d.chart: Chart, ChartLauncher;
Chris@108 9 import org.jzy3d.plot3d.builder: Builder;
Chris@144 10 import org.jzy3d.colors: Color;
Chris@108 11 import org.jzy3d.plot3d.rendering.canvas: Quality;
Chris@119 12 import org.jzy3d.plot3d.rendering.view.modes: ViewPositionMode;
Chris@108 13
Chris@137 14 import javax.imageio: ImageIO;
Chris@137 15
Chris@137 16 import java.io: File;
Chris@137 17
Chris@132 18 chartColours = array [
Chris@132 19 { r = 82, g = 126, b = 154 }, // dark steel blue
Chris@132 20 { r = 161, g = 54, b = 2 }, // red
Chris@132 21 { r = 207, g = 228, b = 148 }, // grey-green
Chris@132 22 { r = 21, g = 183, b = 197 }, // light blue
Chris@132 23 { r = 251, g = 116, b = 43 }, // light red
Chris@132 24 { r = 200, g = 125, b = 234 }, // light purple
Chris@132 25 { r = 126, g = 33, b = 28 }, // dried blood!
Chris@132 26 { r = 188, g = 13, b = 207 }, // mid purple
Chris@131 27 ];
Chris@131 28
Chris@132 29 chartColour n =
Chris@132 30 if n < 0
Chris@132 31 then chartColour (-n)
Chris@132 32 else
Chris@132 33 rgb = chartColours[n % (length chartColours)];
Chris@132 34 new Color(rgb.r / 255.0, rgb.g / 255.0, rgb.b / 255.0);
Chris@132 35 fi;
Chris@132 36
Chris@133 37 newPercentTickRenderer () =
Chris@133 38 (f v = " \(int (v * 100))%";
Chris@133 39 class PercentageTickRenderer extends ITickRenderer
Chris@133 40 String format(double value) f value,
Chris@133 41 String format(float value) f value
Chris@133 42 end;
Chris@133 43 new PercentageTickRenderer());
Chris@133 44
Chris@140 45 newPaddedIntTickRenderer () =
Chris@140 46 (f v = " \(int (v + 0.5))";
Chris@140 47 class PaddedIntTickRenderer extends ITickRenderer
Chris@140 48 String format(double value) f value,
Chris@140 49 String format(float value) f value
Chris@140 50 end;
Chris@140 51 new PaddedIntTickRenderer());
Chris@140 52
Chris@132 53 parseOptions options defaultKeys defaultXKeys =
Chris@132 54 (parsed = {
Chris@133 55 var keys = array (sort defaultKeys),
Chris@132 56 var labels = [:],
Chris@132 57 var animated = false,
Chris@132 58 var normalised = false,
Chris@132 59 var unit = "",
Chris@137 60 var xkeys = array (sort defaultXKeys),
Chris@137 61 var saveTo = "",
Chris@137 62 var display = true,
Chris@132 63 };
Chris@132 64 for options
Chris@132 65 \case of
Chris@133 66 Keys kk: parsed.keys := array kk;
Chris@133 67 XKeys xk: parsed.xkeys := array xk;
Chris@132 68 Animated a: parsed.animated := a;
Chris@132 69 Normalised n: parsed.normalised := n;
Chris@132 70 Unit u: parsed.unit := u;
Chris@132 71 Labels ll: parsed.labels := ll;
Chris@137 72 SaveTo file: parsed.saveTo := file;
Chris@137 73 Display d: parsed.display := d;
Chris@132 74 esac;
Chris@132 75 if empty? parsed.labels then
Chris@132 76 parsed.labels := mapIntoHash id id parsed.keys
Chris@132 77 fi;
Chris@132 78 parsed);
Chris@132 79
Chris@137 80 newChart opts =
Chris@137 81 (quality = Quality#Fastest;
Chris@137 82 quality#setAnimated(opts.animated);
Chris@137 83 // if opts.display then
Chris@137 84 new Chart(quality);
Chris@137 85 // else
Chris@137 86 // new Chart(quality, "offscreen,640,640");
Chris@137 87 // fi);
Chris@137 88 );
Chris@137 89
Chris@137 90 showChart opts chart is 'a -> ~Chart -> () =
Chris@141 91 (if opts.display then
Chris@137 92 \() ChartLauncher#openChart(chart);
Chris@141 93 else
Chris@141 94 \() ChartLauncher#openStaticChart(chart);
Chris@141 95 fi;
Chris@137 96 if opts.saveTo != "" then
Chris@137 97 \() chart#screenshot(opts.saveTo);
Chris@137 98 fi);
Chris@137 99
Chris@132 100 plotBarChart options values =
Chris@132 101 (opts = parseOptions options (keys values) [];
Chris@137 102 chart = newChart opts;
Chris@132 103 var n = length opts.keys;
Chris@119 104 scene = chart#getScene();
Chris@139 105 ticks = new double[n];
Chris@119 106 tickLabels = new TickLabelMap();
Chris@132 107 var i = 0;
Chris@132 108 var x = n - i - 1;
Chris@134 109 total = sum (map do k: if k in values then values[k] else 0 fi done opts.keys);
Chris@132 110 for opts.keys do k:
Chris@136 111 bar = new HistogramBar();
Chris@134 112 v = if k in values then values[k] else 0 fi;
Chris@133 113 v = if opts.normalised and total > 0 then v / total else v fi;
Chris@136 114 bar#setData(new Coord3d(x, 0, 0), v, 0.45, chartColour i);
Chris@136 115 bar#setWireframeDisplayed(false);
Chris@136 116 scene#add(bar);
Chris@132 117 ticks[i] := i;
Chris@132 118 tickLabels#register(x, opts.labels[k]);
Chris@132 119 i := i + 1;
Chris@132 120 x := x - 1;
Chris@119 121 done;
Chris@136 122 chart#getView()#setViewPoint(new Coord3d(pi/2, 0, 0));
Chris@136 123 axes = chart#getAxeLayout();
Chris@136 124 axes#setXAxeLabelDisplayed(false);
Chris@136 125 axes#setYAxeLabelDisplayed(false);
Chris@136 126 axes#setZAxeLabelDisplayed(true);
Chris@136 127 if opts.normalised then
Chris@136 128 axes#setZAxeLabel("");
Chris@136 129 axes#setZTickRenderer(newPercentTickRenderer ());
Chris@135 130 else
Chris@136 131 axes#setZAxeLabel(opts.unit);
Chris@135 132 fi;
Chris@119 133 axes#setXTickProvider(new StaticTickProvider(ticks));
Chris@119 134 axes#setXTickRenderer(tickLabels);
Chris@136 135 axes#setYTickLabelDisplayed(false);
Chris@137 136 showChart opts chart);
Chris@119 137
Chris@132 138 plotLines options values =
Chris@132 139 (opts = parseOptions options (keys values) (keys values[head (keys values)]);
Chris@137 140 chart = newChart opts;
Chris@124 141 scene = chart#getScene();
Chris@132 142 n = length opts.xkeys;
Chris@124 143 var z = 0;
Chris@132 144 for opts.keys do k:
Chris@124 145 v = values[k];
Chris@124 146 x = new float[n];
Chris@124 147 y = new float[n];
Chris@124 148 var i = 0;
Chris@132 149 for opts.xkeys do xk:
Chris@124 150 x[i] := i;
Chris@124 151 y[i] := if xk in v then v[xk] else 0 fi;
Chris@124 152 i := i + 1;
Chris@124 153 done;
Chris@124 154 line = new FlatLine2d(x, y, z);
Chris@124 155 line#setWireframeDisplayed(true);
Chris@132 156 line#setWireframeColor(chartColour z);
Chris@124 157 line#setWireframeWidth(2);
Chris@124 158 line#setFaceDisplayed(false);
Chris@124 159 scene#add(line);
Chris@124 160 z := z + 1;
Chris@124 161 done;
Chris@124 162 chart#getView()#setViewPoint(new Coord3d(0, 0, 0));
Chris@124 163 axes = chart#getAxeLayout();
Chris@124 164 axes#setXAxeLabelDisplayed(false);
Chris@124 165 axes#setYAxeLabelDisplayed(false);
Chris@124 166 axes#setZAxeLabelDisplayed(true);
Chris@132 167 axes#setZAxeLabel(opts.unit);
Chris@124 168 axes#setYTickLabelDisplayed(false);
Chris@137 169 showChart opts chart);
Chris@124 170
Chris@129 171 stack keys xkeys values normalised =
Chris@127 172 (stacked = mapIntoHash id \(mapIntoHash id \{ y0 = 0, y1 = 0 } xkeys) keys;
Chris@125 173 prev = mapIntoHash id \0 xkeys;
Chris@140 174 valueOf k xk =
Chris@140 175 if k in values and xk in values[k]
Chris@140 176 then values[k][xk] else 0
Chris@140 177 fi;
Chris@125 178 for xkeys do xk:
Chris@129 179 total = sum (map do k: valueOf k xk done keys);
Chris@125 180 for keys do k:
Chris@129 181 value =
Chris@129 182 if normalised and total > 0
Chris@129 183 then (valueOf k xk) / total
Chris@129 184 else (valueOf k xk)
Chris@129 185 fi;
Chris@125 186 height = prev[xk] + value;
Chris@127 187 stacked[k][xk] := { y0 = prev[xk], y1 = height };
Chris@125 188 prev[xk] := height;
Chris@125 189 done;
Chris@125 190 done;
Chris@125 191 stacked);
Chris@125 192
Chris@136 193 newRect x y0 y1 z colour is number -> number -> number -> number -> ~Color -> 'a =
Chris@136 194 (poly = new Quad();
Chris@136 195 poly#add(new Point(new Coord3d(x + 0.5, z, y0)));
Chris@136 196 poly#add(new Point(new Coord3d(x + 0.5, z, y1)));
Chris@136 197 poly#add(new Point(new Coord3d(x - 0.5, z, y1)));
Chris@136 198 poly#add(new Point(new Coord3d(x - 0.5, z, y0)));
Chris@136 199 poly#setWireframeDisplayed(true);
Chris@136 200 poly#setWireframeColor(colour);
Chris@136 201 poly#setFaceDisplayed(true);
Chris@136 202 poly#setColor(colour);
Chris@136 203 poly);
Chris@136 204
Chris@132 205 plotStacked options values =
Chris@132 206 (opts = parseOptions options (keys values) (keys values[head (keys values)]);
Chris@137 207 chart = newChart opts;
Chris@125 208 scene = chart#getScene();
Chris@132 209 stacked = stack opts.keys opts.xkeys values opts.normalised;
Chris@125 210 var z = 0;
Chris@130 211 var ty = 0;
Chris@138 212 nxk = length opts.xkeys;
Chris@139 213 xticks = new double[nxk];
Chris@133 214 xtickLabels = new TickLabelMap();
Chris@138 215 for [0..nxk - 1] do x:
Chris@139 216 xticks[x] := x;
Chris@139 217 k = opts.xkeys[x];
Chris@139 218 xtickLabels#register(x, if k in opts.labels then opts.labels[k] else k fi);
Chris@133 219 done;
Chris@132 220 for opts.keys do k:
Chris@127 221 ranges = stacked[k];
Chris@132 222 c = chartColour z;
Chris@138 223 for [0..nxk - 1] do x:
Chris@133 224 xk = opts.xkeys[x];
Chris@127 225 rect = newRect x ranges[xk].y0 ranges[xk].y1 z c;
Chris@127 226 scene#add(rect);
Chris@125 227 done;
Chris@138 228 text = new DrawableTextBitmap(opts.labels[k], new Coord3d(-(nxk/5 + 0.5), z, ty), c);
Chris@128 229 scene#add(text);
Chris@126 230 z := z - 1;
Chris@130 231 ty := ty + 0.1;
Chris@125 232 done;
Chris@129 233 chart#getView()#setViewPoint(new Coord3d(-pi/2, 0, 0));
Chris@125 234 axes = chart#getAxeLayout();
Chris@125 235 axes#setXAxeLabelDisplayed(false);
Chris@139 236 if nxk < 10 then
Chris@139 237 axes#setXTickProvider(new StaticTickProvider(xticks));
Chris@139 238 fi;
Chris@133 239 axes#setXTickRenderer(xtickLabels);
Chris@125 240 axes#setYAxeLabelDisplayed(false);
Chris@125 241 axes#setZAxeLabelDisplayed(true);
Chris@133 242 if opts.normalised then
Chris@133 243 axes#setZAxeLabel("");
Chris@133 244 axes#setZTickRenderer(newPercentTickRenderer ());
Chris@133 245 else
Chris@133 246 axes#setZAxeLabel(opts.unit);
Chris@140 247 axes#setZTickRenderer(newPaddedIntTickRenderer ());
Chris@133 248 fi;
Chris@125 249 axes#setYTickLabelDisplayed(false);
Chris@137 250 showChart opts chart);
Chris@124 251
Chris@115 252 {
Chris@124 253 plotBarChart,
Chris@124 254 plotLines,
Chris@125 255 stack,
Chris@125 256 plotStacked,
Chris@115 257 }
Chris@110 258