if not plotMarks.properties.update then plotMarks.properties.update = {} end
plotMarks.properties.update[colorField] = { scale = "color", field = dataField }
end  
local function getPieChartVisualisation(yCount, innerRadius, outerRadius, linewidth, radiusScale)
local chartvis =
{
type = "arc",
from = { data = "chart", transform = { { field = "y", type = "pie" } } },  
properties =
{
enter = {
innerRadius = { value = innerRadius },
outerRadius = { },
startAngle = { field = "layout_start" },
endAngle = { field = "layout_end" },
stroke = { value = "white" },
strokeWidth = { value = linewidth or 1 }
}
}
}  
if radiusScale then
chartvis.properties.enter.outerRadius.scale = radiusScale.name
chartvis.properties.enter.outerRadius.field = radiusScale.domain.field
else
chartvis.properties.enter.outerRadius.value = outerRadius
end  
addInteractionToChartVisualisation(chartvis, "fill", "x")  
return chartvis
end  
local function getChartVisualisation(chartType, stacked, colorField, yCount, innerRadius, outerRadius, linewidth, alphaScale, radiusScale, lineScale, interpolate)
if chartType == "pie" then return getPieChartVisualisation(yCount, innerRadius, outerRadius, linewidth, radiusScale) end  
local chartvis =
{
type = chartType,
properties =
{
-- chart creation event handler
enter =
{
x = { scale = "x", field = "x" },
y = { scale = "y", field = "y" }
}
}
}
addInteractionToChartVisualisation(chartvis, colorField, "series")
if colorField == "stroke" then
chartvis.properties.enter.strokeWidth = { value = linewidth or 2.5 }
if type(lineScale) =="table" then
chartvis.properties.enter.strokeWidth.value = nil
chartvis.properties.enter.strokeWidth =
{
scale = "line",
field= "series"
}
end
end  
if interpolate then chartvis.properties.enter.interpolate = { value = interpolate } end  
if alphaScale then chartvis.properties.update[colorField .. "Opacity"] = { scale = "transparency" } end
-- for bars and area charts set the lower bound of their areas
if chartType == "rect" or chartType == "area" then
if stacked then
-- for stacked charts this lower bound is the end of the last stacking element
chartvis.properties.enter.y2 = { scale = "y", field = "layout_end" }
else
---
for non-stacking charts the lower bound is y=0
TODO: "yscale.zero" is currently set to "true" for this case, but "false" for all other cases.
For the similar behavior "y2" should actually be set to where y axis crosses the x axis,
if there are only positive or negative values in the data
chartvis.properties.enter.y2 = { scale = "y", value = 0 }
end
end
-- for bar charts ...
if chartType == "rect" then
-- set 1 pixel width between the bars
chartvis.properties.enter.width = { scale = "x", band = true, offset = -1 }
-- for multiple series the bar marking needs to use the "inner" series scale, whereas the "outer" x scale is used by the grouping
if not stacked and yCount > 1 then
chartvis.properties.enter.x.scale = "series"
chartvis.properties.enter.x.field = "series"
chartvis.properties.enter.width.scale = "series"
end
end
-- stacked charts have their own (stacked) y values
if stacked then chartvis.properties.enter.y.field = "layout_start" end  
-- if there are multiple series group these together
if yCount == 1 then
chartvis.from = { data = "chart" }
else
-- if there are multiple series, connect colors to series
chartvis.properties.update[colorField].field = "series"
if alphaScale then chartvis.properties.update[colorField .. "Opacity"].field = "series" end  
-- if there are multiple series, connect linewidths to series
if chartype == "line" then
chartvis.properties.update["strokeWidth"].field = "series"
end  
-- apply a grouping (facetting) transformation
chartvis =
{
type = "group",
marks = { chartvis },
from =
{
data = "chart",
transform =
{
{
type = "facet",
groupby = { "series" }
}
}
}
}
-- for stacked charts apply a stacking transformation
if stacked then
table.insert(chartvis.from.transform, 1, { type = "stack", groupby = { "x" }, sortby = { "-_id" }, field = "y" } )
else
-- for bar charts the series are side-by-side grouped by x
if chartType == "rect" then
-- for bar charts with multiple series: each serie is grouped by the x value, therefore the series need their own scale within each x group
local groupScale =
{
name = "series",
type = "ordinal",
range = "width",
domain = { field = "series" }
}  
chartvis.from.transform[1].groupby = "x"
chartvis.scales = { groupScale }
chartvis.properties = { enter = { x = { field = "key", scale = "x" }, width = { scale = "x", band = true } } }
end
end
end  
return chartvis
end  
local function getTextMarks(chartvis, chartType, outerRadius, scales, radiusScale, yType, showValues)
local properties
if chartType == "rect" then
properties =
{
x = { scale = chartvis.properties.enter.x.scale, field = chartvis.properties.enter.x.field },
y = { scale = chartvis.properties.enter.y.scale, field = chartvis.properties.enter.y.field, offset = -(tonumber(showValues.offset) or -4) },
--dx = { scale = chartvis.properties.enter.x.scale, band = true, mult = 0.5 }, -- for horizontal text
dy = { scale = chartvis.properties.enter.x.scale, band = true, mult = 0.5 }, -- for vertical text
align = { },
baseline = { value = "middle" },
fill = { },
angle = { value = -90 },
fontSize = { value = tonumber(showValues.fontsize) or 11 }
}
if properties.y.offset >= 0 then
properties.align.value = ""
properties.fill.value = showValues.fontcolor or "white"
else
properties.align.value = ""
properties.fill.value = showValues.fontcolor or persistentGrey
end
elseif chartType == "pie" then
properties =
{
x = { group = "width", mult = 0.5 },
y = { group = "height", mult = 0.5 },
radius = { offset = tonumber(showValues.offset) or -4 },
theta = { field = "layout_mid" },
fill = { value = showValues.fontcolor or persistentGrey },
baseline = { },
angle = { },
fontSize = { value = tonumber(showValues.fontsize) or math.ceil(outerRadius / 10) }
}
if (showValues.angle or "midangle") == "midangle" then
properties.align = { value = "" }
properties.angle = { field = "layout_mid", mult = 180.0 / math.pi }  
if properties.radius.offset >= 0 then
properties.baseline.value = "bottom"
else
if not showValues.fontcolor then properties.fill.value = "white" end
properties.baseline.value = "top"
end
elseif tonumber(showValues.angle) then
-- qunatize scale for aligning text on half-circle and on half-circle
local alignScale = { name = "align", type = "quantize", domainMin = 0.0, domainMax = math.pi * 2, range = { "", "" } }
table.insert(scales, alignScale)  
properties.align = { scale = alignScale.name, field = "layout_mid" }
properties.angle = { value = tonumber(showValues.angle) }
properties.baseline.value = "middle"
if not tonumber(showValues.offset) then properties.radius.offset = 4 end
end  
if radiusScale then
properties.radius.scale = radiusScale.name
properties.radius.field = radiusScale.domain.field
else
properties.radius.value = outerRadius
end
end  
if properties then
if showValues.format then
local template = "datum.y"
if yType == "integer" or yType == "number" then template = template .. "|number:'" .. showValues.format .. "'"
elseif yType == "date" then template = template .. "|time:" .. showValues.format .. "'"
end
properties.text = { template = "" }
else
properties.text = { field = "y" }
end  
local textmarks =
{
type = "text",
properties =
{
enter = properties
}
}
if chartvis.from then textmarks.from = copy(chartvis.from) end  
return textmarks
end
end  
local function getSymbolMarks(chartvis, symSize, symShape, symStroke, noFill, alphaScale)  
local symbolmarks
symbolmarks =
{
type = "symbol",
properties =
{
enter =
{
x = { scale = "x", field = "x" },
y = { scale = "y", field = "y" },
strokeWidth = { value = symStroke },
stroke = { scale = "color", field = "series" },
fill = { scale = "color", field = "series" },
}
}
}
if type(symShape) == "string" then
symbolmarks.properties.enter.shape = { value = symShape }
end
if type(symShape) == "table" then