1 /** 2 This module contains the different examples that are shown in the README 3 4 It will only be included in unittest code, but is empty otherwise. 5 */ 6 module example; 7 8 version (unittest) 9 10 import dunit.toolkit; 11 import std.stdio : writeln; 12 13 /// 14 unittest 15 { 16 /// http://blackedder.github.io/ggplotd/images/function.png 17 import std.random : uniform; 18 import std.typecons : Tuple; 19 import ggplotd.stat : statFunction; 20 import ggplotd.ggplotd : GGPlotD; 21 import ggplotd.geom : geomLine, geomPoint; 22 import ggplotd.range : mergeRange; 23 24 auto f = (double x) { return x / (1 + x); }; 25 26 auto aes = statFunction(f, 0.0, 10); 27 auto gg = GGPlotD().put(geomLine(aes)); 28 29 // Generate some noisy points 30 auto f2 = (double x) { return x / (1 + x) * uniform(0.75, 1.25); }; 31 auto aes2 = f2.statFunction(0.0, 10, 25); 32 33 // Show points in different colour 34 auto withColour = Tuple!(string, "colour")("aquamarine").mergeRange(aes2); 35 gg = gg.put(withColour.geomPoint); 36 37 gg.save("function.png"); 38 } 39 40 /// 41 unittest 42 { 43 /// http://blackedder.github.io/ggplotd/images/hist2D.svg 44 import std.array : array; 45 import std.algorithm : map; 46 import std.range : iota, zip; 47 import std.random : uniform; 48 49 import ggplotd.aes : aes; 50 import ggplotd.colour : colourGradient; 51 import ggplotd.colourspace : XYZ; 52 import ggplotd.geom : geomHist2D; 53 import ggplotd.ggplotd : GGPlotD, putIn; 54 import ggplotd.legend : continuousLegend; 55 56 auto xs = iota(0,500,1).map!((x) => uniform(0.0,5)+uniform(0.0,5)) 57 .array; 58 auto ys = iota(0,500,1).map!((y) => uniform(0.0,5)+uniform(0.0,5)) 59 .array; 60 auto gg = xs.zip(ys) 61 .map!((t) => aes!("x","y")(t[0], t[1])) 62 .geomHist2D.putIn(GGPlotD()); 63 // Use a different colour scheme 64 gg.put( colourGradient!XYZ( "white-cornflowerBlue-crimson" ) ); 65 66 gg.put(continuousLegend); 67 68 gg.save( "hist2D.svg" ); 69 } 70 71 /// 72 unittest 73 { 74 /// http://blackedder.github.io/ggplotd/images/filled_density.svg 75 import std.array : array; 76 import std.algorithm : map; 77 import std.range : repeat, iota, chain, zip; 78 import std.random : uniform; 79 80 import ggplotd.aes : aes; 81 import ggplotd.geom : geomDensity; 82 import ggplotd.ggplotd : GGPlotD, putIn; 83 import ggplotd.legend : discreteLegend; 84 auto xs = iota(0,50,1).map!((x) => uniform(0.0,5)+uniform(0.0,5)).array; 85 auto cols = "a".repeat(25).chain("b".repeat(25)); 86 auto gg = xs.zip(cols, 0.45.repeat(xs.length)) 87 .map!((a) => aes!("x", "colour", "fill")(a[0], a[1], a[2])) 88 .geomDensity 89 .putIn(GGPlotD()); 90 gg = discreteLegend.putIn(gg); 91 gg.save( "filled_density.svg" ); 92 } 93 94 /// 95 unittest 96 { 97 /// http://blackedder.github.io/ggplotd/images/density2D.png 98 import std.algorithm : map; 99 import std.range : iota, zip; 100 import std.random : uniform, Random, unpredictableSeed; 101 102 import ggplotd.aes : aes; 103 import ggplotd.colour : colourGradient; 104 import ggplotd.colourspace : XYZ; 105 import ggplotd.geom : geomDensity2D; 106 import ggplotd.ggplotd : GGPlotD, putIn; 107 import ggplotd.legend : continuousLegend; 108 109 // For debugging reasons, print out the current seed 110 import std.stdio : writeln; 111 auto seed = unpredictableSeed; 112 auto rnd = Random(seed); 113 //auto rnd = Random(1193462362); // This is a seed that currently fails. Use it for debugging 114 writeln("Random seed MCMC: ", seed); 115 116 auto xs = iota(0,500,1).map!((x) => uniform(0.0,5, rnd)+uniform(0.0,5, rnd)); 117 auto ys = iota(0,500,1).map!((y) => uniform(0.5,1.5, rnd)+uniform(0.5,1.5, rnd)); 118 auto gg = zip(xs, ys) 119 .map!((a) => aes!("x","y")(a[0], a[1])) 120 .geomDensity2D 121 .putIn( GGPlotD() ); 122 // Use a different colour scheme 123 gg.put( colourGradient!XYZ( "white-cornflowerBlue-crimson" ) ); 124 gg.put(continuousLegend); 125 126 gg.save( "density2D.png" ); 127 } 128 129 /// 130 unittest 131 { 132 /// http://blackedder.github.io/ggplotd/images/labels.png 133 import std.algorithm : map; 134 import std.range : zip; 135 import std.math : PI; 136 137 import ggplotd.aes : aes; 138 import ggplotd.geom : geomPoint, geomLabel; 139 import ggplotd.ggplotd : GGPlotD; 140 import ggplotd.axes : xaxisRange, yaxisRange; 141 auto dt = zip( [0.0,1,2,3,4], [4.0,3,2,1,0], 142 ["center", "left", "right", "bottom", "top"], 143 [0.0, 0.0, 0.0, 0.0, 0.0], 144 ["center", "left", "right", "bottom", "top"]) 145 .map!((a) => aes!("x", "y", "label", "angle", "justify") 146 (a[0], a[1], a[2], a[3], a[4])); 147 148 auto gg = GGPlotD() 149 .put(geomPoint( dt )) 150 .put(geomLabel(dt)) 151 .put(xaxisRange(-2,11)) 152 .put(yaxisRange(-2,11)); 153 154 auto dt2 = zip( [1.0,2,3,4,5], [5.0,4,3,2,1], 155 ["center", "left", "right", "bottom", "top"], 156 [0.5*PI, 0.5*PI, 0.5*PI, 0.5*PI, 0.5*PI], 157 ["center", "left", "right", "bottom", "top"]) 158 .map!((a) => aes!("x", "y", "label", "angle", "justify") 159 (a[0], a[1], a[2], a[3], a[4])); 160 gg.put( geomLabel(dt2) ).put(geomPoint(dt2)); 161 162 auto dt3 = zip( [1.0,2,4,6,7], [8.0,7,5,3,2], 163 ["center", "left", "right", "bottom", "top"], 164 [0.25*PI, 0.25*PI, 0.25*PI, 0.25*PI, 0.25*PI], 165 ["center", "left", "right", "bottom", "top"]) 166 .map!((a) => aes!("x", "y", "label", "angle", "justify") 167 (a[0], a[1], a[2], a[3], a[4])); 168 gg.put( geomLabel(dt3) ).put(geomPoint(dt3)); 169 170 gg.save( "labels.png" ); 171 } 172 173 auto runMCMC() { 174 import std.algorithm : map; 175 import std.array : array; 176 import std.math : pow; 177 import std.range : iota; import std.random : Random, unpredictableSeed; 178 // For debugging reasons, print out the current seed 179 import std.stdio : writeln; 180 auto seed = unpredictableSeed; 181 auto rnd = Random(seed); 182 //auto rnd = Random(1193462362); // This is a seed that currently fails. Use it for debugging 183 writeln("Random seed MCMC: ", seed); 184 //writeln("Random seed MCMC: ", rnd.front); 185 186 187 import dstats.random : rNormal; 188 return iota(0,1000).map!((i) { 189 auto x = rNormal(1, 0.5, rnd); 190 auto y = rNormal(pow(x,3), 0.5, rnd); 191 auto z = rNormal(x + y, 0.5, rnd); 192 return [x, y, z]; 193 }).array; 194 } 195 196 /// 197 unittest 198 { 199 // http://blackedder.github.io/ggplotd/images/parameter_distribution.png 200 import std.algorithm : map; 201 import std.format : format; 202 import ggplotd.aes : aes; 203 import ggplotd.axes : xaxisLabel, yaxisLabel; 204 import ggplotd.geom : geomDensity, geomDensity2D; 205 import ggplotd.ggplotd : Facets, GGPlotD, putIn; 206 import ggplotd.colour : colourGradient; 207 import ggplotd.colourspace : XYZ; 208 209 // Running MCMC for a model that takes 3 parameters 210 // Will return 1000 posterior samples for the 3 parameters 211 // [[par1, par2, par3], ...] 212 auto samples = runMCMC(); 213 214 // Facets can be used for multiple subplots 215 Facets facets; 216 217 // Cycle over the parameters 218 foreach(i; 0..3) 219 { 220 foreach(j; 0..3) 221 { 222 auto gg = GGPlotD(); 223 224 gg = format("Parameter %s", i).xaxisLabel.putIn(gg); 225 if (i != j) 226 { 227 // Change the colourGradient used 228 gg = colourGradient!XYZ( "white-cornflowerBlue-crimson" ) 229 .putIn(gg); 230 gg = format("Parameter %s", j).yaxisLabel.putIn(gg); 231 gg = samples.map!((sample) => aes!("x", "y")(sample[i], sample[j])) 232 .geomDensity2D 233 .putIn(gg); 234 } else { 235 gg = "Density".yaxisLabel.putIn(gg); 236 gg = samples.map!((sample) => aes!("x", "y")(sample[i], sample[j])) 237 .geomDensity 238 .putIn(gg); 239 } 240 facets = gg.putIn(facets); 241 } 242 } 243 facets.save("parameter_distribution.png", 670, 670); 244 } 245 246 /// 247 unittest 248 { 249 // http://blackedder.github.io/ggplotd/images/diamonds.png 250 import std.csv : csvReader; import std.file : readText; 251 import std.algorithm : map; 252 import std.array : array; 253 import ggplotd.aes : aes; 254 import ggplotd.axes : xaxisLabel, yaxisLabel; 255 import ggplotd.ggplotd : GGPlotD, putIn; 256 import ggplotd.geom : geomPoint; 257 258 259 struct Diamond { 260 double carat; 261 string clarity; 262 double price; 263 } 264 265 // Read the data 266 auto diamonds = readText("test_files/diamonds.csv").csvReader!(Diamond)( 267 ["carat","clarity","price"]); 268 269 auto gg = diamonds.map!((diamond) => 270 // Map data to aesthetics (x, y and colour) 271 aes!("x", "y", "colour", "size")(diamond.carat, diamond.price, diamond.clarity, 0.8)) 272 .array 273 // Draw points 274 .geomPoint.putIn(GGPlotD()); 275 276 // Axis labels 277 gg = "Carat".xaxisLabel.putIn(gg); 278 gg = "Price".yaxisLabel.putIn(gg); 279 gg.save("diamonds.png"); 280 } 281 282 /// Multiple histograms examples 283 unittest 284 { 285 // http://blackedder.github.io/ggplotd/images/filled_hist.svg 286 import std.array : array; 287 import std.algorithm : map; 288 import std.range : repeat, iota, chain, zip; 289 import std.random : uniform; 290 291 import ggplotd.aes : aes; 292 import ggplotd.geom : geomHist; 293 import ggplotd.ggplotd : putIn, GGPlotD; 294 295 auto xs = iota(0,50,1).map!((x) => uniform(0.0,5)+uniform(0.0,5)).array; 296 auto cols = "a".repeat(25).chain("b".repeat(25)); 297 auto gg = xs.zip(cols) 298 .map!((a) => aes!("x", "colour", "fill")(a[0], a[1], 0.45)) 299 .geomHist 300 .putIn(GGPlotD()); 301 gg.save( "filled_hist.svg" ); 302 } 303 304 /// Size as third dimension 305 unittest 306 { 307 import std.range : zip; 308 import std.algorithm : map; 309 import ggplotd.aes : aes; 310 import ggplotd.geom : geomPoint; 311 import ggplotd.ggplotd : putIn, GGPlotD; 312 import ggplotd.axes : xaxisRange, yaxisRange; 313 314 auto gg = [0.0,1.0,2.0].zip([0.5, 0.25, 0.75], [1000, 10000, 50000]) 315 .map!((a) => aes!("x", "y", "size")(a[0], a[1], a[2])) 316 .geomPoint 317 .putIn(GGPlotD()); 318 gg.put(xaxisRange(-0.5, 2.5)); 319 gg.put(yaxisRange(0, 1)); 320 gg.save("sizeStore.png"); 321 } 322 323 /// Boxplot example 324 unittest 325 { 326 // http://blackedder.github.io/ggplotd/images/boxplot.svg 327 import std.array : array; 328 import std.algorithm : map; 329 import std.range : repeat, iota, chain, zip; 330 import std.random : uniform; 331 332 import ggplotd.aes : aes; 333 import ggplotd.geom : geomBox; 334 import ggplotd.ggplotd : GGPlotD, putIn; 335 336 auto xs = iota(0,50,1).map!((x) => uniform(0.0,5)+uniform(0.0,5)); 337 auto cols = "a".repeat(25).chain("b".repeat(25)); 338 auto gg = xs.zip(cols) 339 .map!((a) => aes!("x", "colour", "fill", "label" )(a[0], a[1], 0.45, a[1])) 340 .geomBox 341 .putIn(GGPlotD()); 342 gg.save( "boxplot.svg" ); 343 } 344 345 /// Changing axes details 346 unittest 347 { 348 // http://blackedder.github.io/ggplotd/images/axes.svg 349 import std.array : array; 350 import std.math : sqrt; 351 import std.algorithm : map; 352 import std.range : iota; 353 354 import ggplotd.aes : aes; 355 import ggplotd.axes : xaxisLabel, yaxisLabel, xaxisOffset, yaxisOffset, 356 xaxisRange, yaxisRange, xaxisTextAngle; 357 import ggplotd.geom : geomLine; 358 import ggplotd.ggplotd : GGPlotD, putIn, Margins, title; 359 import ggplotd.stat : statFunction; 360 361 auto f = (double x) { return x/(1+x); }; 362 auto gg = statFunction(f, 0, 10.0) 363 .geomLine 364 .putIn(GGPlotD()); 365 366 // Setting range and label for xaxis 367 gg.put( xaxisRange( 0, 8 ) ) 368 .put( xaxisLabel( "My xlabel" ) ) 369 .put( xaxisTextAngle( 90 ) ); 370 // Setting range and label for yaxis 371 gg.put( yaxisRange( 0, 2.0 ) ).put( yaxisLabel( "My ylabel" ) ); 372 373 // change offset 374 gg.put( xaxisOffset( 0.25 ) ).put( yaxisOffset( 0.5 ) ); 375 376 // Change Margins 377 gg.put( Margins( 60, 60, 40, 30 ) ); 378 379 // Set a title 380 gg.put( title( "And now for something completely different" ) ); 381 382 // Saving on a 500x300 pixel surface 383 gg.save( "axes.svg", 500, 300 ); 384 } 385 386 /// Example from the readme using aes and merge 387 unittest 388 { 389 import ggplotd.aes : aes, merge; 390 struct Data1 391 { 392 double value1 = 1.0; 393 double value2 = 2.0; 394 } 395 396 Data1 dat1; 397 398 // Merge to add a value 399 auto merged = aes!("x", "y")(dat1.value1, dat1.value2) 400 .merge( 401 aes!("colour")("a") 402 ); 403 assertEqual(merged.x, 1.0); 404 assertEqual(merged.colour, "a"); 405 406 // Merge to a second data struct 407 struct Data2 { string colour = "b"; } 408 Data2 dat2; 409 410 auto merged2 = aes!("x", "y")(dat1.value1, dat1.value2) 411 .merge( dat2 ); 412 assertEqual(merged2.x, 1.0); 413 assertEqual(merged2.colour, "b"); 414 415 // Overriding a field 416 auto merged3 = aes!("x", "y")(dat1.value1, dat1.value2) 417 .merge( 418 aes!("y")("a") 419 ); 420 assertEqual(merged3.y, "a"); 421 } 422 423 /// Polygon 424 unittest 425 { 426 import std.range : zip; 427 import std.algorithm : map; 428 import ggplotd.aes : aes; 429 import ggplotd.geom : geomPolygon; 430 import ggplotd.ggplotd : GGPlotD, putIn; 431 432 // http://blackedder.github.io/ggplotd/images/polygon.png 433 auto gg = zip([1, 0, 0.0], [1, 1, 0.0], [1, 0.1, 0]) 434 .map!((a) => aes!("x", "y", "colour")(a[0], a[1], a[2])) 435 .geomPolygon 436 .putIn(GGPlotD()); 437 gg.save( "polygon.png" ); 438 } 439 440 /// Log scale 441 unittest 442 { 443 import std.range : zip; 444 import std.algorithm : map; 445 import ggplotd.aes : aes; 446 import ggplotd.scale : scale; 447 import ggplotd.ggplotd : GGPlotD, putIn; 448 import ggplotd.geom : geomLine; 449 450 // http://blackedder.github.io/ggplotd/images/logScale.png 451 auto gg = zip([1.0, 10.0, 15], [30, 100, 1000.0]) 452 .map!((a) => aes!("x", "y")(a[0], a[1])) 453 .geomLine 454 .putIn(GGPlotD()); 455 456 gg = scale!("x")("log").putIn(gg); 457 gg = scale!("y")("log10").putIn(gg); 458 gg.save( "logScale.png" ); 459 }