{deck}
version:1
card:0
size:[512,342]
name:"Plot"
author:"John Earnest"

{fonts}
deckbuilder:"%%[encoded data, 12424 characters]"

{card:Index}
script:"Index.0"
{widgets}
field1:{"type":"field","size":[308,50],"pos":[103,60],"locked":1,"border":1,"align":"center","value":{"text":["","Plot:\n","Simple charts and graphs for Decker"],"font":["","deckbuilder","menu"],"arg":["","",""]}}
field2:{"type":"field","size":[229,151],"pos":[273,170],"locked":1,"border":0,"value":"The plot module provides a set of functions for drawing basic data visualizations: scatterplots, lineplots, histograms, bar charts, box-and-whisker plots, and pie charts.\n\nEach function takes a canvas and a data source, and draws the plot to fill the canvas, complete with margins, axes, and labels, as appropriate. Axis ranges and ticks are automatically computed from the dataset.\n\nThis module also includes some simple data preparation utilities and a function for computing aesthetically pleasing axis labels."}
index:{"type":"field","size":[253,162],"pos":[11,170],"locked":1,"volatile":1,"script":"Index.1","scrollbar":1}
version:{"type":"field","size":[25,14],"pos":[7,22],"locked":1,"volatile":1,"border":0}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}

{script:Index.0}
on view do
 bullet:image["%%IMG0AAYADQAAAAB49Pz8/HgAAAA="]
 i:select c:key t:value..widgets.title.text where value..widgets.title from deck.cards
 index.value:raze each row in rows i
  rtext.make["" "" bullet],
  rtext.make["  "],
  rtext.make[("%s\n" format row.t) "mono" row.c]
 end
 version.text:"v%0.1f" format deck.modules.plot.version
end
{end}

{script:Index.1}
on link val do
 go[val "BoxIn" 15]
end
{end}

{script:Index.2}
on click do
 t.Prev:"SlideRight"
 t.Next:"SlideLeft"
 t.Index:"BoxOut"
 go[me.text t[me.text] 15]
end
{end}

{card:scatterplot}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Scatter Plots"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,139],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"d:insert x y g with\n 10 11 \"A\"\n 15 12 \"B\"\n 23  8 \"A\"\n 19  7 \"A\"\n 12 11 \"B\"\n -9 -2 \"A\"\nend\nplot.scatter[target d]\n\n"}
try:{"type":"button","size":[60,20],"pos":[252,164],"script":"scatterplot.1","text":"Try It!"}
target:{"type":"canvas","size":[176,129],"pos":[326,175],"locked":1,"volatile":1,"brush":3,"pattern":13,"scale":1}
field2:{"type":"field","size":[250,100],"pos":[252,45],"locked":1,"border":0,"value":{"text":["","plot.scatter[canvas data]","\n\n\"canvas\" is any canvas widget.\n\n\"data\" is a list or table. if it's a list, interpret it as the y axis, with an implicit sequential x axis. if it's a table, look for columns x, y, and g (group). With a \"g\" column, group by that column to form multiple series, which will each be assigned a distinct pattern."],"font":["","mono",""],"arg":["","",""]}}
ex2:{"type":"field","size":[236,111],"pos":[10,193],"border":1,"scrollbar":1,"style":"code","value":"d:100,115,210,120,93,130\nplot.scatter[target d]"}
button4:{"type":"button","size":[60,20],"pos":[252,284],"script":"scatterplot.2","text":"Try It!"}
field1:{"type":"field","size":[176,14],"pos":[326,159],"locked":1,"border":0,"align":"center","value":"target"}
button5:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplot.3","text":"Styling","style":"rect"}

{script:scatterplot.0}
on view do
 try.event.click
end
{end}

{script:scatterplot.1}
on click do
 eval[ex1.text () 1]
end
{end}

{script:scatterplot.2}
on click do
 eval[ex2.text () 1]
end
{end}

{script:scatterplot.3}
on click do
 go[card.name,"style" "BoxOut" 15]
end
{end}

{card:lineplot}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Line Plots"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,182],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"d:insert x y g with\n 1  5 0\n 2  7 0\n 3 12 0\n 4  6 0\n 5  9 0\n 1  4 1\n 2  6 1\n 3 13 1\n 5 15 1\nend\nplot.line[target d]"}
try:{"type":"button","size":[60,20],"pos":[252,207],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,100],"pos":[252,45],"locked":1,"border":0,"value":{"text":["","plot.line[canvas data]","\n\n\"canvas\" is any canvas widget.\n\n\"data\" is a list or table. if it's a list, interpret it as the y axis, with an implicit sequential x axis. if it's a table, look for columns x, y, and g (group). With a \"g\" column, group by that column to form multiple series, which will each be assigned a distinct pattern."],"font":["","mono",""],"arg":["","",""]}}
ex2:{"type":"field","size":[236,70],"pos":[10,234],"border":1,"scrollbar":1,"style":"code","value":"d:100,115,210,120,93,130\nplot.line[target d]"}
button4:{"type":"button","size":[60,20],"pos":[252,284],"script":"scatterplot.2","text":"Try It!"}
target:{"type":"canvas","size":[176,129],"pos":[326,175],"locked":1,"volatile":1,"brush":1,"pattern":13,"scale":1}
field1:{"type":"field","size":[176,14],"pos":[326,159],"locked":1,"border":0,"align":"center","value":"target"}
button5:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplot.3","text":"Styling","style":"rect"}

{card:histogram}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Histograms"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,259],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"d:100,115,210,120,93,130\n\nplot.hist[target d]\n"}
try:{"type":"button","size":[60,20],"pos":[252,284],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,100],"pos":[252,45],"locked":1,"border":0,"value":{"text":["","plot.hist[canvas data]","\n\n\"canvas\" is any canvas widget.\n\n\"data\" is a list of y values."],"font":["","mono",""],"arg":["","",""]}}
target:{"type":"canvas","size":[176,129],"pos":[326,175],"locked":1,"volatile":1,"scale":1}
field1:{"type":"field","size":[176,14],"pos":[326,159],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplot.3","text":"Styling","style":"rect"}

{card:barchart}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Bar Charts"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,259],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"t.apple:10\nt.banana:37\nt.cherry:29\n\nplot.bar[target t]\n"}
try:{"type":"button","size":[60,20],"pos":[252,284],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,100],"pos":[252,45],"locked":1,"border":0,"value":{"text":["","plot.bar[canvas data]","\n\n\"canvas\" is any canvas widget.\n\n\"data\" is a dictionary of numbers. Keys of the dictionary are used as axis labels."],"font":["","mono",""],"arg":["","",""]}}
target:{"type":"canvas","size":[176,129],"pos":[326,175],"locked":1,"volatile":1,"scale":1}
field1:{"type":"field","size":[176,14],"pos":[326,159],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplot.3","text":"Styling","style":"rect"}

{card:boxplot}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Box Plots"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,259],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"t.one:-3,5\nt.two:1,12.2,15\nt.three:-5,-4,2,5,8\n\nplot.box[target t]\n"}
try:{"type":"button","size":[60,20],"pos":[252,284],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,100],"pos":[252,45],"locked":1,"border":0,"value":{"text":["","plot.box[canvas data]","\n\n\"canvas\" is any canvas widget.\n\n\"data\" is a dictionary of lists. Keys of the dictionary are used as axis labels. If a value contains two numbers, draw it as a range. Three numbers are drawn with a median line, and five numbers are drawn as a box with whiskers."],"font":["","mono",""],"arg":["","",""]}}
target:{"type":"canvas","size":[176,129],"pos":[326,175],"locked":1,"volatile":1,"scale":1}
field1:{"type":"field","size":[176,14],"pos":[326,159],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplot.3","text":"Styling","style":"rect"}

{card:piechart}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Pie Charts"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,259],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"d:5,15,33\n\nplot.pie[target d]\n"}
try:{"type":"button","size":[60,20],"pos":[252,284],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,100],"pos":[252,45],"locked":1,"border":0,"value":{"text":["","plot.pie[canvas data]","\n\n\"canvas\" is any canvas widget.\n\n\"data\" is a list of numbers. Pie slices will be drawn proportionally based on their contribution to the sum of data."],"font":["","mono",""],"arg":["","",""]}}
target:{"type":"canvas","size":[176,129],"pos":[326,175],"locked":1,"volatile":1,"brush":1,"scale":1}
field1:{"type":"field","size":[176,14],"pos":[326,159],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplot.3","text":"Styling","style":"rect"}

{card:styling}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Styling"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,107],"pos":[10,198],"border":1,"scrollbar":1,"style":"code","value":"etc.bgdata:44\netc.brush:0\n\nd:100,115,210,120,93,130\nplot.line[target d etc]"}
try:{"type":"button","size":[60,20],"pos":[252,285],"script":"scatterplot.1","text":"Try It!"}
target:{"type":"canvas","size":[176,129],"pos":[47,60],"locked":1,"volatile":1,"scale":1}
field2:{"type":"field","size":[250,235],"pos":[252,45],"locked":1,"border":0,"value":"In addition to the required arguments, each of the plot drawing functions can be supplied one extra dictionary argument (\"etc\"). If they are present, the following keys within that dictionary control the visual appearance of various parts of each plot:\n\n- margin: blank pixels at each edge of the canvas.\n\n- font: a font name or value for drawing axes.\n\n- bg: a pattern index applied to the entire background of the plot.\n\n- bgdata: a pattern index applied to the data region of the plot (supercedes bg).\n\n- brush: the canvas brush id which should be used for drawing data.\n\n- stroke: a pattern index for drawing axes and outlines.\n\n- fill: a list of pattern indices used to draw each series."}
field1:{"type":"field","size":[176,14],"pos":[47,44],"locked":1,"border":0,"align":"center","value":"target"}

{card:scatterplotstyle}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Styling Scatter Plots"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,260],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"d:insert x y g with\n 10 11 \"A\"\n 15 12 \"B\"\n 23  8 \"A\"\n 19  7 \"A\"\n 12 11 \"B\"\n -9 -2 \"C\"\nend\nplot.scatter[target d]\n\netc.margin:20\netc.font:\"menu\"\netc.bg:44\netc.bgdata:39\netc.brush:4\netc.stroke:46\netc.fill:33,36,37\n\nplot.scatter[target d etc]"}
try:{"type":"button","size":[60,20],"pos":[252,285],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,63],"pos":[252,45],"locked":1,"border":0,"value":"An example of a scatter plot with custom styling."}
target:{"type":"canvas","size":[242,143],"pos":[256,131],"locked":1,"volatile":1,"font":"menu","brush":4,"pattern":37,"scale":1}
field1:{"type":"field","size":[242,14],"pos":[256,115],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplotstyle.0","text":"Usage","style":"rect"}

{script:scatterplotstyle.0}
on click do
 go[(-count "style") drop card.name "BoxOut" 15]
end
{end}

{card:lineplotstyle}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Styling Line Plots"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,260],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"d:insert x y g with\n 1  5 0\n 2  7 0\n 3 12 0\n 4  6 0\n 5  9 0\n 1  4 1\n 2  6 1\n 3 13 1\n 5 15 1\nend\n\netc.margin:20\netc.font:\"menu\"\netc.bg:44\netc.bgdata:39\netc.brush:0\netc.stroke:46\netc.fill:colors.red,colors.blue\n\nplot.line[target d etc]"}
try:{"type":"button","size":[60,20],"pos":[252,285],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,63],"pos":[252,45],"locked":1,"border":0,"value":"An example of a line plot with custom styling."}
target:{"type":"canvas","size":[242,143],"pos":[256,131],"locked":1,"volatile":1,"font":"menu","pattern":38,"scale":1}
field1:{"type":"field","size":[242,14],"pos":[256,115],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplotstyle.0","text":"Usage","style":"rect"}

{card:histogramstyle}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Styling Histograms"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,260],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"etc.margin:20\netc.font:\"menu\"\netc.bg:44\netc.bgdata:39\netc.brush:0\netc.stroke:46\netc.fill:colors.blue\n\nd:100,115,210,120,93,130\nplot.hist[target d etc]\n"}
try:{"type":"button","size":[60,20],"pos":[252,285],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,63],"pos":[252,45],"locked":1,"border":0,"value":"An example of a histogram with custom styling."}
target:{"type":"canvas","size":[242,143],"pos":[256,131],"locked":1,"volatile":1,"font":"menu","pattern":46,"scale":1}
field1:{"type":"field","size":[242,14],"pos":[256,115],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplotstyle.0","text":"Usage","style":"rect"}

{card:barchartstyle}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Styling Bar Charts"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,260],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"etc.margin:20\netc.font:\"menu\"\netc.bg:44\netc.bgdata:39\netc.brush:0\netc.stroke:46\netc.fill:36,37,38\n\nt.apple:10\nt.banana:37\nt.cherry:29\n\nplot.bar[target t etc]\n"}
try:{"type":"button","size":[60,20],"pos":[252,285],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,63],"pos":[252,45],"locked":1,"border":0,"value":"An example of a bar chart with custom styling."}
target:{"type":"canvas","size":[242,143],"pos":[256,131],"locked":1,"volatile":1,"font":"menu","pattern":46,"scale":1}
field1:{"type":"field","size":[242,14],"pos":[256,115],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplotstyle.0","text":"Usage","style":"rect"}

{card:boxplotstyle}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Styling Box Plots"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,260],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"etc.margin:20\netc.font:\"menu\"\netc.bg:44\netc.bgdata:39\netc.brush:0\netc.stroke:46\netc.fill:33,35,36\n\nt.one:-3,5\nt.two:1,12.2,15\nt.three:-5,-4,2,5,8\n\nplot.box[target t etc]\n"}
try:{"type":"button","size":[60,20],"pos":[252,285],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,63],"pos":[252,45],"locked":1,"border":0,"value":"An example of a box plot with custom styling."}
target:{"type":"canvas","size":[242,143],"pos":[256,131],"locked":1,"volatile":1,"font":"menu","pattern":46,"scale":1}
field1:{"type":"field","size":[242,14],"pos":[256,115],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplotstyle.0","text":"Usage","style":"rect"}

{card:piechartstyle}
script:"scatterplot.0"
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Styling Pie Charts"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,260],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"etc.margin:20\netc.bg:44\netc.stroke:46\netc.fill:33,35,36\n\nd:2,15,33\n\nplot.pie[target d etc]\n"}
try:{"type":"button","size":[60,20],"pos":[252,285],"script":"scatterplot.1","text":"Try It!"}
field2:{"type":"field","size":[250,63],"pos":[252,45],"locked":1,"border":0,"value":"An example of a pie chart with custom styling."}
target:{"type":"canvas","size":[242,143],"pos":[256,131],"locked":1,"volatile":1,"font":"menu","brush":1,"pattern":46,"scale":1}
field1:{"type":"field","size":[242,14],"pos":[256,115],"locked":1,"border":0,"align":"center","value":"target"}
button4:{"type":"button","size":[60,20],"pos":[146,312],"script":"scatterplotstyle.0","text":"Usage","style":"rect"}

{card:windowing}
script:"scatterplot.0"
{widgets}
examples:{"type":"contraption","size":[236,111],"pos":[10,194],"script":"windowing.0","def":"scriptViewer","widgets":{"o":{"size":[100,22],"pos":[259,1],"value":"scatter\nline\nhist\nbar\nbox"},"c":{"size":[236,18]},"i":{"size":[100,27],"pos":[259,36],"interval":[0,4]},"scr":{"size":[232,90]}}}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"Windowing"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
field2:{"type":"field","size":[250,76],"pos":[252,45],"locked":1,"border":0,"value":"Plotting functions normally calculate a plotting interval based on the range of input data, but in some cases it's desirable to specify these explicitly for consistency between plots or over time. Minimum and/or maximum values for the x and y axes can be specified in \"etc\" where applicable. Note that the provided values will be rounded to \"nice\" intervals for the axes."}
grid1:{"type":"grid","size":[250,98],"pos":[252,132],"locked":1,"scrollbar":0,"lines":0,"widths":[73],"format":"sBBBB","value":{"plot type":["scatter","line","histogram","bar","box","pie"],"xmin":[1,1,0,1,1,0],"xmax":[1,1,0,1,1,0],"ymin":[1,1,1,0,0,0],"ymax":[1,1,1,0,0,0]},"col":4}
target:{"type":"canvas","size":[176,129],"pos":[47,60],"locked":1,"volatile":1,"brush":3,"scale":1}
field1:{"type":"field","size":[176,14],"pos":[47,44],"locked":1,"border":0,"align":"center","value":"target"}
scatter:{"type":"button","size":[22,18],"pos":[296,254],"script":"windowing.1","show":"none"}
line:{"type":"button","size":[22,18],"pos":[332,254],"script":"windowing.2","show":"none"}
hist:{"type":"button","size":[22,18],"pos":[367,254],"script":"windowing.3","show":"none"}
bar:{"type":"button","size":[22,18],"pos":[404,254],"script":"windowing.4","show":"none"}
box:{"type":"button","size":[22,18],"pos":[440,254],"script":"windowing.5","show":"none"}
try:{"type":"button","size":[60,20],"pos":[252,285],"script":"windowing.6","text":"Try It!"}

{script:windowing.0}
on change do
 view[]
end
{end}

{script:windowing.1}
etc.xmin:-10
etc.xmax:10
etc.ymin:100
etc.ymax:200
d:100,115,210,120,93,130
plot.scatter[target d etc]

{end}

{script:windowing.2}
etc.xmin:-10
etc.xmax:10
etc.ymin:100
etc.ymax:200
etc.brush:0
d:100,115,210,120,93,130
plot.line[target d etc]
{end}

{script:windowing.3}
etc.ymin:50
etc.ymax:150
d:100,115,210,120,93,130
plot.hist[target d etc]
{end}

{script:windowing.4}
etc.xmin:-10
etc.xmax:30
t.apple:10
t.banana:37
t.cherry:29
plot.bar[target t etc]
{end}

{script:windowing.5}
etc.xmin:-10
etc.xmax:10
t.one:-3,5
t.two:1,12.2,15
t.three:-5,-4,2,5,8
plot.box[target t etc]
{end}

{script:windowing.6}
on click do
 eval[card.widgets[examples.value].script () 1]
end
{end}

{card:label}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"plot.label[]"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,261],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"plot.label[-.34 2.812]\n# (-1,0,1,2,3)\n\nplot.label[241 999]\n# (200,400,600,800,1000)\n\n"}
field2:{"type":"field","size":[250,115],"pos":[252,45],"locked":1,"border":0,"value":{"text":["","plot.label[min max]","\n\nGenerate a list of aesthetically-pleasing axis labels given a minimum and maximum interval using Paul Heckbert's \"loose labels\" method.\n\n\"min\" and \"max\" are numbers."],"font":["","mono",""],"arg":["","",""]}}

{card:pivot}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"plot.pivot[]"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,161],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"d:insert country name year pop with\n \"NL\" \"Amsterdam\"     2000 1005\n \"NL\" \"Amsterdam\"     2020 1158\n \"US\" \"Seattle\"       2000  564\n \"US\" \"Seattle\"       2020  738\n \"US\" \"New York City\" 2000 8015\n \"US\" \"New York City\" 2020 8772\nend\n\ngrid.value:plot.pivot[\n \"year\" \"pop\" d\n]"}
field2:{"type":"field","size":[250,185],"pos":[252,45],"locked":1,"border":0,"value":{"text":["","plot.pivot[group val tab]\n","\nExplode a pair of columns in a table out into multiple columns. This may be useful for displaying summaries for human consumption.\n\n\"group\" is a string column name from the input table which contains the names of the new columns to create.\n\n\"val\" is a string column name from the input table which contains the values to ungroup into the new columns.\n\n\"tab\" is an input table.\n\nFor correct results, every result row should have a complete set of group/value input rows which appear in a consistent order for each group."],"font":["","mono",""],"arg":["","",""]}}
grid:{"type":"grid","size":[236,96],"pos":[10,211],"volatile":1,"widths":[29]}
try:{"type":"button","size":[60,20],"pos":[252,287],"script":"scatterplot.1","text":"Try It!"}

{card:unpivot}
{widgets}
button1:{"type":"button","size":[60,20],"pos":[442,312],"script":"Index.2","text":"Next","style":"rect"}
button2:{"type":"button","size":[60,20],"pos":[10,312],"script":"Index.2","text":"Prev","style":"rect"}
title:{"type":"field","size":[492,17],"pos":[10,22],"locked":1,"font":"menu","show":"invert","border":1,"align":"center","value":"plot.unpivot[]"}
button3:{"type":"button","size":[60,20],"pos":[78,312],"script":"Index.2","text":"Index","style":"rect"}
ex1:{"type":"field","size":[236,161],"pos":[10,45],"border":1,"scrollbar":1,"style":"code","value":"d:insert id dept jan feb mar with\n 1 \"electronics\"   1   2   3\n 2 \"clothes\"      10  20  30\n 3 \"cars\"        100 200 300\nend\n\ngrid.value:plot.unpivot[\n \"month\"\n \"sales\"\n (\"jan\",\"feb\",\"mar\")\n d\n]"}
field2:{"type":"field","size":[250,204],"pos":[252,45],"locked":1,"border":0,"value":{"text":["","plot.unpivot[group val src tab]\n","\nCombine several columns from a table into a pair of columns organized by series. This can be useful for converting data where series are each separate columns into a single \"grouping\" column as expected by the plot functions.\n\n\"group\" is a string column name which will contain the original column that each value came from.\n\n\"val\" is a string column name which will contain each original value.\n\n\"src\" is a list of string column names to collate together into \"group\" and \"val\".\n\n\"tab\" is an input table."],"font":["","mono",""],"arg":["","",""]}}
grid:{"type":"grid","size":[236,96],"pos":[10,211],"volatile":1,"widths":[29]}
try:{"type":"button","size":[60,20],"pos":[252,287],"script":"scatterplot.1","text":"Try It!"}

{module:plot}
description:"draw graphs and plots to canvases"
version:2
{script}
local grays:(1,13,12,9,8,5)

on label x y do
 # Paul Heckbert's "loose labels" method
 # for generating axis labels and ranges:
 on nice x round do
  f:x/10^e:floor(ln x)/(ln n:10)
  if round
   if f<7   n:5 end
   if f<3   n:2 end
   if f<1.5 n:1 end
  else
   if !f>5  n:5 end
   if !f>2  n:2 end
   if !f>1  n:1 end
  end
  n*10^e
 end
 d:nice[nice[y-x 0]/5 1]
 a:d* floor x/d
 b:d*-floor-y/d
 v:() while a<b+.5*d  v:v,a  a:a+d end v
end

on plot_series c data draw etc do
 c.font:      if "font"   in etc etc.font   else "body" end
 local margin:if "margin" in etc etc.margin else     10 end
 local bg    :if "bg"     in etc etc.bg     else      0 end
 local bgdata:if "bgdata" in etc etc.bgdata else      0 end
 local stroke:if "stroke" in etc etc.stroke else      1 end
 local fill  :if "fill"   in etc etc.fill   else  grays end
 if "number"~typeof fill fill:list fill end

 if !"table"~typeof data
  data:select x:keys data y:value from data
 end
 nd.x:if "x" in data data.x else (update x:gindex by g from data).x end
 nd.y:if "y" in data data.y else data end
 nd.g:if "g" in data data.g else 0*nd.x end
 data:update g:group by g from table nd

 xaxis:label[
  if "xmin" in etc etc.xmin else min data.x end
  if "xmax" in etc etc.xmax else max data.x end
 ]
 yaxis:label[
  if "ymin" in etc etc.ymin else min data.y end
  if "ymax" in etc etc.ymax else max data.y end
 ]
 gmin:(first xaxis),first yaxis
 gmax:(last  xaxis),last  yaxis
 axes:(max each x in yaxis c.font.textsize[x][0] end),12
 psize:c.lsize-axes+2*margin
 ppos:margin+axes*1,0

 c.pattern:bg
 c.rect[0,0 c.size]
 c.pattern:bgdata
 c.rect[ppos psize]

 c.pattern:stroke
 c.brush:0
 c.rect[ppos+psize*0,1  psize[0],1]
 c.rect[ppos+psize*0,1  1,-psize[1]]
 on map pos do
  r:(pos-gmin)/gmax-gmin
  ppos+psize*r[0],1-r[1]
 end
 each v in xaxis
  p:map[v,first yaxis]
  c.rect[p 1,3]
  c.text[v p+0,5 "top_center"]
 end
 each v in yaxis
  p:map[(first xaxis),v]
  c.rect[p -3,1]
  c.text[v p-5,0 "center_right"]
 end
 c.clip[ppos-0,1 psize+1]
 extract
  (c.pattern:fill[(count fill)%first g]),
  draw[each v i in x map[v,y[i]] end]
 by g from data
 c.clip[]
end

on plot_category c data line draw etc do
 c.font:      if "font"   in etc etc.font   else  "body" end
 local margin:if "margin" in etc etc.margin else      10 end
 local bg    :if "bg"     in etc etc.bg     else       0 end
 local bgdata:if "bgdata" in etc etc.bgdata else       0 end
 local stroke:if "stroke" in etc etc.stroke else       1 end
 local fill  :if "fill"   in etc etc.fill   else list 13 end
 if "number"~typeof fill fill:list fill end

 xaxis:label[
  if "xmin" in etc etc.xmin else min 0,min data end
  if "xmax" in etc etc.xmax else max 0,max data end
 ]
 gmin:first xaxis
 gmax:last  xaxis
 axes:(max each v k in data c.font.textsize[k][0] end),12
 psize:c.lsize-axes+2*margin
 ppos:margin+axes*1,0

 c.pattern:bg
 c.rect[0,0 c.size]
 c.pattern:bgdata
 c.rect[ppos psize]

 c.pattern:stroke
 c.brush:0
 c.rect[ppos+psize*0,1 psize[0],1]
 on mapx x do ppos[0]+psize[0]*(x-gmin)/gmax-gmin end
 each v in xaxis
  p:mapx[v],(ppos+psize)[1]
  c.rect[p 1,3]
  c.text[v p+0,5 "top_center"]
 end
 origin:mapx[0]
 yaxis:origin,ppos[1]
 c.pattern:line
 c.rect[yaxis 1,psize[1]]

 bh:psize[1]/count data
 each v k i in data
  p:ppos+(0,1)*(bh*i)+bh/2
  c.pattern:stroke
  c.text[k p-5,0 "center_right"]
  c.pattern:fill[(count fill)%i]
  c.clip[ppos-0,1 psize+1]
  draw[origin,p[1] each x in (),v mapx[x] end bh]
  c.clip[]
 end
end

on plot_scatter c data etc do
 local data_brush:if "brush" in etc etc.brush else 3 end
 on draw d do
  c.brush:data_brush
  each v in d c.line[v] end
 end
 plot_series[c data draw etc]
end

on plot_line c data etc do
 local data_brush:if "brush" in etc etc.brush else 1 end
 on draw d do
  c.brush:data_brush
  c.line[d]
 end
 plot_series[c data draw etc]
end

on plot_hist c data etc do
 c.font:      if "font"   in etc etc.font   else  "body" end
 local margin:if "margin" in etc etc.margin else      10 end
 local bg    :if "bg"     in etc etc.bg     else       0 end
 local bgdata:if "bgdata" in etc etc.bgdata else       0 end
 local stroke:if "stroke" in etc etc.stroke else       1 end
 local fill  :if "fill"   in etc etc.fill   else list 13 end
 if "number"~typeof fill fill:list fill end

 xdata:range count data
 xaxis:label[min xdata max xdata]
 yaxis:label[
  if "ymin" in etc etc.ymin else min data end
  if "ymax" in etc etc.ymax else max data end
 ]
 if 5>count data xaxis:xdata end
 gmin:(  first xaxis),first yaxis
 gmax:(1+last  xaxis),last  yaxis
 axes:(max each x in yaxis c.font.textsize[x][0] end),12
 psize:c.lsize-axes+2*margin
 ppos:margin+axes*1,0
 bwid:psize[0]/count data

 c.pattern:bg
 c.rect[0,0 c.size]
 c.pattern:bgdata
 c.rect[ppos psize]

 c.brush:0
 c.clip[ppos-0,1 psize+1]
 on map pos xoff do
  r:(pos-gmin)/gmax-gmin
  (xoff,0)+ppos+psize*r[0],1-r[1]
 end
 each v i in data
  v:map[i,v bwid/2]
  s:1+psize[1]-v[1]-ppos[1]
  c.pattern:fill[(count fill)%i]
  c.rect[v 1+bwid,s "top_center"]
 end
 c.clip[]
 c.pattern:stroke
 c.rect[ppos+psize*0,1  psize[0],1]
 c.rect[ppos+psize*0,1  1,-psize[1]]
 each v in xaxis
  p:map[v,first yaxis bwid/2]
  c.rect[p 1,3]
  c.text[v p+0,5 "top_center"]
 end
 each v in yaxis
  p:map[(first xaxis),v]
  c.rect[p -3,1]
  c.text[v p-5,0 "center_right"]
 end
end

on plot_bar c data etc do
 local stroke:if "stroke" in etc etc.stroke else 1 end
 local axes:  if "axes"   in etc etc.axes   else 1 end
 on draw start stops height do
  a:start-height*0,.4
  b:((first stops)-start[0]),.8*height
  c.rect[a b]
  c.pattern:stroke
  c.box[a b]
 end
 plot_category[c data axes draw etc]
end

on plot_box c data etc do
 local stroke:if "stroke" in etc etc.stroke else 1 end
 on draw start stops height do
  on stop x do floor stops[x],start[1] end
  on woff x do (1+x),height*.5         end
  a:stop[0]
  b:stop[-1+count stops]
  local col:c.pattern
  c.pattern:stroke
  c.line[a b]
  c.rect[a woff[] "center_left"]
  c.rect[b woff[] "center_left"]
  c.pattern:col
  if 2<count stops
   m:0.5*count stops
   q1:stop[m-1] q2:stop[m] q3:stop[m+1]
   c.rect [q1 woff[q3[0]-q1[0]] "center_left"]
   c.pattern:stroke
   c.box  [q1 woff[q3[0]-q1[0]] "center_left"]
   c.rect [q2 woff[           ] "center_left"]
  end
 end
 if !"fill" in etc etc.fill:32 end
 plot_category[c data 18 draw etc]
end

on plot_pie c data etc do
 local margin    :if "margin" in etc etc.margin else    10 end
 local bg        :if "bg"     in etc etc.bg     else     0 end
 local data_brush:if "brush"  in etc etc.brush  else     1 end
 local stroke    :if "stroke" in etc etc.stroke else     1 end
 local fill      :if "fill"   in etc etc.fill   else grays end
 if "number"~typeof fill fill:list fill end
 
 local vals:(range data)/sum range data
 local psize:c.lsize-2*margin
 local radius:.5*min psize
 local center:margin+psize/2
 
 c.pattern:bg
 c.rect[0,0 c.size]
 c.brush:data_brush
 local start:0
 on wedge v do
  r:radius*unit -2*pi*start+v*(range 21)/20
  start:start+v
  (list center),(flip center+flip r),(list center)
 end
 each v i in vals
  local w:wedge[v]
  c.pattern:fill[(count fill)%i]
  c.poly[w]
  c.pattern:stroke
  c.line[w]
 end
end

on unpivot key value src tab do
 eval["select
  %s
  %v:src
  %v:raze column@src
 by index from tab" format (" " fuse src drop keys tab),key,value () 1].value
end
on pivot key value tab do
 keep:(key,value) drop keys tab
 dkey:keys tab[key] dict ()
 head:(" ","%q:first %v") format keep join keep
 data:(" ","%q:%s[%i]"  ) format dkey join ((count dkey) take list value) join (keys dkey)
 ident:" join " fuse keep
 eval["select %s %s by %s from tab" format head,data,ident () 1].value
end

mod.label  :label
mod.unpivot:unpivot
mod.pivot  :pivot
mod.scatter:plot_scatter
mod.line   :plot_line
mod.hist   :plot_hist
mod.bar    :plot_bar
mod.box    :plot_box
mod.pie    :plot_pie
{end}

{contraption:scriptViewer}
size:[100,100]
resizable:1
margin:[3,20,3,3]
description:"a tabbed editor for viewing and editing the scripts of one or more widgets on the current card."
version:1.1
image:"%%IMG2AGQAZAD/AP8A/wD/AP8A/wCqAWUgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAQIgYgECIGIBAiBiAWU="
script:"scriptViewer.0p"
template:"on change do\n \nend"
attributes:{"name":["options_text"],"label":["Sources"],"type":["code"]}
{widgets}
o:{"type":"field","size":[100,20],"pos":[123,1],"show":"none","style":"plain","value":"card"}
c:{"type":"canvas","size":[100,18],"pos":[0,0],"locked":1,"volatile":1,"show":"transparent","border":0,"pattern":32,"scale":1}
i:{"type":"slider","size":[100,25],"pos":[123,32],"show":"none","interval":[0,2]}
scr:{"type":"field","size":[96,79],"pos":[2,19],"volatile":1,"border":0,"scrollbar":1,"style":"code"}

{script:scriptViewer.0p}
on get_options_text do o.text end
on set_options_text x do
 o.text:x
 i.interval:0,(count "\n" split o.text)-1
 view[]
end
on get_options do "\n" split o.text end
on set_options x do set_options_text["\n" fuse x] x end
on get_value do get_options[][i.value] end
on set_value x do v:get_options[] i.value:sum (range count v)*v=x x view[] end

bf:image["%%IMG2AAsABwADAQUABQEBIAUBAQADAQEgBwEBAAEBASAJAQIgCQECIAkBDA=="] bb:image["%%IMG2AAsABwADAQUABQEBIAUBAQADAQEgAQEFIAEBAQABAQEgAQEHIAEBAiABAQcgAQECIAEBByABAQIgAQEHIAEBAQ=="]

on target do
 val:get_value[]
 if val~"deck" deck elseif val~"card" deck.card else deck.card.widgets[val] end
end
on change do
 target[].script:scr.text
end

on view do
 c.font:card.font
 c.clear[]
 v:get_options[]
 w:(c.size[0]-20)/count v
 each x ix in v
  sel:ix~i.value
  b:(ix*w),0,(w+ix<-1+count v),c.size[1]
  c.segment[(bf,bb)[sel] b 5,4,5,2]
  c.pattern:(1,32)[sel]
  c.text[x b+(0,1,0,0) "center"]
 end
 scr.text:target[].script
 scr.locked:card.locked
end

on click pos do
 v:get_options[]
 w:(c.size[0]-20)/count v
 set_value[v[floor(first pos)/w]]
 card.event.change
end
{end}

