Changes

11,210 bytes added ,  09:32, 20 August 2020
m
symbols disabled for bar charts
Line 1: Line 1: −
-- ATTENTION: Please edit this code at https://de.wikipedia.org/wiki/Modul:Graph
+
 
--             This way all wiki languages can stay in sync. Thank you!
+
-- ATTENTION: Please edit this code at https://de.wikipedia.org/wiki/Modul:Graph
 +
--         This way all wiki languages can stay in sync. Thank you!
 
--
 
--
 +
-- BUGS: X-Axis label format bug? (xAxisFormat =) https://en.wikipedia.org/wiki/Template_talk:Graph:Chart#X-Axis_label_format_bug?_(xAxisFormat_=)
 +
-- linewidths - doesnt work for two values (eg 0, 1) but work if added third value of both are zeros? Same for marksStroke - probably bug in Graph extension
 +
-- clamp - "clamp" used to avoid marks outside marks area, "clip" should be use instead but not working in Graph extension, see https://phabricator.wikimedia.org/T251709
 +
-- TODO: 
 +
-- marks:
 +
-- - line strokeDash + serialization,
 +
-- - symStroke serialization
 +
-- - symbolsNoFill serialization
 +
-- - arbitrary SVG path symbol shape as symbolsShape argument
 +
-- - annotations
 +
-- - vertical / horizontal line at specific values
 +
-- - rectangle shape for x,y data range
 +
-- - graph type serialization (deep rebuild reqired)
 +
--     - second axis (deep rebuild required - assignment of series to one of two axies)
 +
 
-- Version History (_PLEASE UPDATE when modifying anything_):
 
-- Version History (_PLEASE UPDATE when modifying anything_):
 +
--  2020-08-08 New logic for "nice" for x axis (problem with scale when xType = "date") and grid
 +
--  2020-06-21 Serializes symbol size
 +
--              transparent symbosls (from line colour) - buggy (incorrect opacity on overlap with line)
 +
--              Linewidth serialized with "linewidths"
 +
--              Variable symbol size and shape of symbols on line charts, default showSymbols = 2, default symbolsShape = circle, symbolsStroke = 0
 +
--              p.chartDebuger(frame) for easy debug and JSON output
 +
--  2020-06-07 Allow lowercase variables for use with [[Template:Wikidata list]]
 +
--  2020-05-27 Map: allow specification which feature to display and changing the map center
 +
--  2020-04-08 Change default showValues.fontcolor from black to persistentGrey
 +
--  2020-04-06 Logarithmic scale outputs wrong axis labels when "nice"=true
 +
--  2020-03-11 Allow user-defined scale types, e.g. logarithmic scale
 +
--  2019-11-08 Apply color-inversion-friendliness to legend title, labels, and xGrid
 
--  2019-01-24 Allow comma-separated lists to contain values with commas
 
--  2019-01-24 Allow comma-separated lists to contain values with commas
 
--  2018-10-13 Fix browser color-inversion issues via #54595d per [[mw:Template:Graph:PageViews]]
 
--  2018-10-13 Fix browser color-inversion issues via #54595d per [[mw:Template:Graph:PageViews]]
Line 15: Line 43:     
local p = {}
 
local p = {}
 +
 +
--add debug text to this string with eg. debuglog = debuglog .. "" .. "\n\n"  .. "- " .. debug.traceback() .. "result type: ".. type(result) ..  " result: \n\n" .. mw.dumpObject(result)
 +
--invoke chartDebuger() to get graph JSON and this string
 +
debuglog = "Debug " .. "\n\n"
    
local baseMapDirectory = "Module:Graph/"
 
local baseMapDirectory = "Module:Graph/"
 +
local persistentGrey = "#54595d"
 +
 +
local shapes = {}
 +
shapes = {
 +
circle = "circle", x= "M-.5,-.5L.5,.5M.5,-.5L-.5,.5" , square = "square",
 +
cross = "cross", diamond = "diamond", triangle_up = "triangle-up",
 +
triangle_down = "triangle-down", triangle_right = "triangle-right",
 +
triangle_left = "triangle-left",
 +
banana = "m -0.5281,0.2880 0.0020,0.0192 m 0,0 c 0.1253,0.0543 0.2118,0.0679 0.3268,0.0252 0.1569,-0.0582 0.3663,-0.1636 0.4607,-0.3407 0.0824,-0.1547 0.1202,-0.2850 0.0838,-0.4794 l 0.0111,-0.1498 -0.0457,-0.0015 c -0.0024,0.3045 -0.1205,0.5674 -0.3357,0.7414 -0.1409,0.1139 -0.3227,0.1693 -0.5031,0.1856 m 0,0 c 0.1804,-0.0163 0.3622,-0.0717 0.5031,-0.1856 0.2152,-0.1739 0.3329,-0.4291 0.3357,-0.7414 l -0.0422,0.0079 c 0,0 -0.0099,0.1111 -0.0227,0.1644 -0.0537,0.1937 -0.1918,0.3355 -0.3349,0.4481 -0.1393,0.1089 -0.2717,0.2072 -0.4326,0.2806 l -0.0062,0.0260"
 +
  }
 +
    
local function numericArray(csv)
 
local function numericArray(csv)
Line 36: Line 79:  
end
 
end
 
end
 
end
return result, isInteger
+
 
 +
    return result, isInteger
 
end
 
end
   Line 63: Line 107:  
function p.map(frame)
 
function p.map(frame)
 
-- map path data for geographic objects
 
-- map path data for geographic objects
local basemap = frame.args.basemap or "WorldMap-iso2.json"
+
local basemap = frame.args.basemap or "Template:Graph:Map/Inner/Worldmap2c-json" -- WorldMap name and/or location may vary from wiki to wiki
 
-- scaling factor
 
-- scaling factor
 
local scale = tonumber(frame.args.scale) or 100
 
local scale = tonumber(frame.args.scale) or 100
Line 69: Line 113:  
local projection = frame.args.projection or "equirectangular"
 
local projection = frame.args.projection or "equirectangular"
 
-- defaultValue for geographic objects without data
 
-- defaultValue for geographic objects without data
local defaultValue = frame.args.defaultValue
+
local defaultValue = frame.args.defaultValue or frame.args.defaultvalue
local scaleType = frame.args.scaleType or "linear"
+
local scaleType = frame.args.scaleType or frame.args.scaletype or "linear"
 
-- minimaler Wertebereich (nur für numerische Daten)
 
-- minimaler Wertebereich (nur für numerische Daten)
local domainMin = tonumber(frame.args.domainMin)
+
local domainMin = tonumber(frame.args.domainMin or frame.args.domainmin)
 
-- maximaler Wertebereich (nur für numerische Daten)
 
-- maximaler Wertebereich (nur für numerische Daten)
local domainMax = tonumber(frame.args.domainMax)
+
local domainMax = tonumber(frame.args.domainMax or frame.args.domainmax)
 
-- Farbwerte der Farbskala (nur für numerische Daten)
 
-- Farbwerte der Farbskala (nur für numerische Daten)
local colorScale = frame.args.colorScale or "category10"
+
local colorScale = frame.args.colorScale or frame.args.colorscale or "category10"
 
-- show legend
 
-- show legend
 
local legend = frame.args.legend
 
local legend = frame.args.legend
 +
-- the map feature to display
 +
    local feature = frame.args.feature or "countries"
 +
    -- map center
 +
    local center = numericArray(frame.args.center)
 
-- format JSON output
 
-- format JSON output
 
local formatJson = frame.args.formatjson
 
local formatJson = frame.args.formatjson
Line 143: Line 191:  
}
 
}
 
end
 
end
 
+
 
-- get map url
 
-- get map url
 
local basemapUrl
 
local basemapUrl
Line 168: Line 216:  
{
 
{
 
-- data source for map paths data
 
-- data source for map paths data
name = "countries",
+
name = feature,
 
url = basemapUrl,
 
url = basemapUrl,
format = { type = "topojson", feature = "countries" },
+
format = { type = "topojson", feature = feature },
 
transform =
 
transform =
 
{
 
{
Line 178: Line 226:  
value = "data", -- data source
 
value = "data", -- data source
 
scale = scale,
 
scale = scale,
translate = { 0, 0 },
+
                        translate = { 0, 0 },
 +
                        center = center,
 
projection = projection
 
projection = projection
 
},
 
},
Line 198: Line 247:  
{
 
{
 
type = "path",
 
type = "path",
from = { data = "countries" },
+
from = { data = feature },
 
properties =
 
properties =
 
{
 
{
Line 239: Line 288:  
if not xType then xType = "string" end
 
if not xType then xType = "string" end
 
end
 
end
   
return x, xType, xMin, xMax
 
return x, xType, xMin, xMax
 
end
 
end
Line 311: Line 359:  
end
 
end
   −
local function getXScale(chartType, stacked, xMin, xMax, xType)
+
local function getXScale(chartType, stacked, xMin, xMax, xType, xScaleType)
 
if chartType == "pie" then return end
 
if chartType == "pie" then return end
   Line 317: Line 365:  
{
 
{
 
name = "x",
 
name = "x",
type = "linear",
   
range = "width",
 
range = "width",
 
zero = false, -- do not include zero value
 
zero = false, -- do not include zero value
nice = true,  -- force round numbers for y scale
   
domain = { data = "chart", field = "x" }
 
domain = { data = "chart", field = "x" }
 
}
 
}
 +
if xScaleType then xscale.type = xScaleType else xscale.type = "linear" end
 
if xMin then xscale.domainMin = xMin end
 
if xMin then xscale.domainMin = xMin end
 
if xMax then xscale.domainMax = xMax end
 
if xMax then xscale.domainMax = xMax end
Line 332: Line 379:  
xscale.type = "ordinal"
 
xscale.type = "ordinal"
 
if not stacked then xscale.padding = 0.2 end -- pad each bar group
 
if not stacked then xscale.padding = 0.2 end -- pad each bar group
else
+
else  
if xType == "date" then xscale.type = "time"
+
if xType == "date" then  
 +
xscale.type = "time"
 
elseif xType == "string" then
 
elseif xType == "string" then
 
xscale.type = "ordinal"
 
xscale.type = "ordinal"
Line 339: Line 387:  
end
 
end
 
end
 
end
 
+
if xType and xType ~= "date" and xScaleType ~= "log" then xscale.nice = true end -- force round numbers for x scale, but "log" and "date" scale outputs a wrong "nice" scale
 
return xscale
 
return xscale
 
end
 
end
   −
local function getYScale(chartType, stacked, yMin, yMax, yType)
+
local function getYScale(chartType, stacked, yMin, yMax, yType, yScaleType)
 
if chartType == "pie" then return end
 
if chartType == "pie" then return end
   Line 349: Line 397:  
{
 
{
 
name = "y",
 
name = "y",
type = "linear",
   
range = "height",
 
range = "height",
 
-- area charts have the lower boundary of their filling at y=0 (see marks.properties.enter.y2), therefore these need to start at zero
 
-- area charts have the lower boundary of their filling at y=0 (see marks.properties.enter.y2), therefore these need to start at zero
 
zero = chartType ~= "line",
 
zero = chartType ~= "line",
nice = true
+
nice = yScaleType ~= "log" -- force round numbers for y scale, but log scale outputs a wrong "nice" scale
 
}
 
}
 +
if yScaleType then yscale.type = yScaleType else yscale.type = "linear" end
 
if yMin then yscale.domainMin = yMin end
 
if yMin then yscale.domainMin = yMin end
 
if yMax then yscale.domainMax = yMax end
 
if yMax then yscale.domainMax = yMax end
Line 405: Line 453:  
end
 
end
 
return alphaScale
 
return alphaScale
 +
end
 +
 +
local function getLineScale(linewidths, chartType)
 +
local lineScale = {}
 +
 +
lineScale =
 +
    {
 +
        name = "line",
 +
        type = "ordinal",
 +
        range = linewidths,
 +
        domain = { data = "chart", field = "series" }
 +
    }
 +
 +
return lineScale
 +
end
 +
 +
local function getSymSizeScale(symSize)
 +
local SymSizeScale = {}
 +
SymSizeScale =
 +
      {
 +
        name = "symSize",
 +
        type = "ordinal",
 +
        range = symSize,
 +
        domain = { data = "chart", field = "series" }
 +
        }
 +
 +
return SymSizeScale
 +
end
 +
 +
local function getSymShapeScale(symShape)
 +
local SymShapeScale = {}
 +
SymShapeScale =
 +
      {
 +
        name = "symShape",
 +
        type = "ordinal",
 +
        range = symShape,
 +
        domain = { data = "chart", field = "series" }
 +
        }
 +
 +
return SymShapeScale
 
end
 
end
   Line 463: Line 551:  
end
 
end
   −
local function getChartVisualisation(chartType, stacked, colorField, yCount, innerRadius, outerRadius, linewidth, alphaScale, radiusScale, interpolate)
+
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
 
if chartType == "pie" then return getPieChartVisualisation(yCount, innerRadius, outerRadius, linewidth, radiusScale) end
   Line 482: Line 570:  
if colorField == "stroke" then
 
if colorField == "stroke" then
 
chartvis.properties.enter.strokeWidth = { value = linewidth or 2.5 }
 
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
 
end
   Line 522: Line 618:  
chartvis.properties.update[colorField].field = "series"
 
chartvis.properties.update[colorField].field = "series"
 
if alphaScale then chartvis.properties.update[colorField .. "Opacity"].field = "series" end
 
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
 
-- apply a grouping (facetting) transformation
 
chartvis =
 
chartvis =
Line 584: Line 687:  
else
 
else
 
properties.align.value = "left"
 
properties.align.value = "left"
properties.fill.value = showValues.fontcolor or "black"
+
properties.fill.value = showValues.fontcolor or persistentGrey
 
end
 
end
 
elseif chartType == "pie" then
 
elseif chartType == "pie" then
Line 593: Line 696:  
radius = { offset = tonumber(showValues.offset) or -4 },
 
radius = { offset = tonumber(showValues.offset) or -4 },
 
theta = { field = "layout_mid" },
 
theta = { field = "layout_mid" },
fill = { value = showValues.fontcolor or "black" },
+
fill = { value = showValues.fontcolor or persistentGrey },
 
baseline = { },
 
baseline = { },
 
angle = { },
 
angle = { },
Line 652: Line 755:  
end
 
end
   −
local function getSymbolMarks(chartvis)
+
local function getSymbolMarks(chartvis, symSize, symShape, symStroke, noFill, alphaScale)
local symbolmarks =
+
 
 +
local symbolmarks
 +
symbolmarks =
 
{
 
{
 
type = "symbol",
 
type = "symbol",
Line 662: Line 767:  
x = { scale = "x", field = "x" },
 
x = { scale = "x", field = "x" },
 
y = { scale = "y", field = "y" },
 
y = { scale = "y", field = "y" },
 +
strokeWidth = { value = symStroke },
 +
stroke = { scale = "color", field = "series" },
 
fill = { scale = "color", field = "series" },
 
fill = { scale = "color", field = "series" },
shape = "circle",
  −
size = { value = 49 }
   
}
 
}
 
}
 
}
 
}
 
}
 +
if type(symShape) == "string" then
 +
symbolmarks.properties.enter.shape = { value = symShape }
 +
end
 +
if type(symShape) == "table" then
 +
symbolmarks.properties.enter.shape = { scale = "symShape", field = "series" }
 +
end
 +
if type(symSize) == "number" then
 +
symbolmarks.properties.enter.size = { value = symSize }
 +
end
 +
if type(symSize) == "table" then
 +
symbolmarks.properties.enter.size = { scale = "symSize", field = "series" }
 +
end
 +
if noFill then
 +
symbolmarks.properties.enter.fill = nil
 +
end
 +
if alphaScale then
 +
symbolmarks.properties.enter.fillOpacity =
 +
{ scale = "transparency", field = "series" }
 +
symbolmarks.properties.enter.strokeOpacity =
 +
{ scale = "transparency", field = "series" }
 +
end
 
if chartvis.from then symbolmarks.from = copy(chartvis.from) end
 
if chartvis.from then symbolmarks.from = copy(chartvis.from) end
 
+
   
 
return symbolmarks
 
return symbolmarks
 
end
 
end
Line 676: Line 802:  
local xAxis, yAxis
 
local xAxis, yAxis
 
if chartType ~= "pie" then
 
if chartType ~= "pie" then
if xType == "integer" and not xAxisFormat then xAxisFormat = "d" end
+
if xType == "integer" then xAxisFormat = "d" end
 +
-- if not xAxisFormat then xAxisFormat = "d" end
 
xAxis =
 
xAxis =
 
{
 
{
Line 683: Line 810:  
title = xTitle,
 
title = xTitle,
 
format = xAxisFormat,
 
format = xAxisFormat,
grid = xGrid ~= "0"
+
grid = xGrid
 
}
 
}
 
if xAxisAngle then
 
if xAxisAngle then
Line 692: Line 819:  
title =
 
title =
 
{
 
{
fill = { value = "#54595d" }
+
fill = { value = persistentGrey }
 
},
 
},
 
labels =
 
labels =
Line 698: Line 825:  
angle = { value = xAxisAngle },
 
angle = { value = xAxisAngle },
 
align = { value = xAxisAlign },
 
align = { value = xAxisAlign },
fill = { value = "#54595d" }
+
fill = { value = persistentGrey }
 
},
 
},
 
ticks =
 
ticks =
 
{
 
{
stroke = { value = "#54595d" }
+
stroke = { value = persistentGrey }
 
},
 
},
 
axis =
 
axis =
 
{
 
{
stroke = { value = "#54595d" },
+
stroke = { value = persistentGrey },
 
strokeWidth = { value = 2 }
 
strokeWidth = { value = 2 }
 +
},
 +
grid =
 +
{
 +
stroke = { value = persistentGrey }
 
}
 
}
 
}
 
}
Line 715: Line 846:  
title =
 
title =
 
{
 
{
fill = { value = "#54595d" }
+
fill = { value = persistentGrey }
 
},
 
},
 
labels =
 
labels =
 
{
 
{
fill = { value = "#54595d" }
+
fill = { value = persistentGrey }
 
},
 
},
 
ticks =
 
ticks =
 
{
 
{
stroke = { value = "#54595d" }
+
stroke = { value = persistentGrey }
 
},
 
},
 
axis =
 
axis =
 
{
 
{
stroke = { value = "#54595d" },
+
stroke = { value = persistentGrey },
 
strokeWidth = { value = 2 }
 
strokeWidth = { value = 2 }
 +
},
 +
grid =
 +
{
 +
stroke = { value = persistentGrey }
 
}
 
}
 
}
 
}
 
end
 
end
   −
if yType == "integer" and not yAxisFormat then yAxisFormat = "d" end
+
if yType == "integer" then yAxisFormat = "d" end
 +
if not yAxisFormat then yAxisFormat = "d" end
 
yAxis =
 
yAxis =
 
{
 
{
Line 740: Line 876:  
title = yTitle,
 
title = yTitle,
 
format = yAxisFormat,
 
format = yAxisFormat,
grid = yGrid ~= "0"
+
grid = yGrid
 
}
 
}
 
yAxis.properties =
 
yAxis.properties =
Line 746: Line 882:  
title =
 
title =
 
{
 
{
fill = { value = "#54595d" }
+
fill = { value = persistentGrey }
 
},
 
},
 
labels =
 
labels =
 
{
 
{
fill = { value = "#54595d" }
+
fill = { value = persistentGrey }
 
},
 
},
 
ticks =
 
ticks =
 
{
 
{
stroke = { value = "#54595d" }
+
stroke = { value = persistentGrey }
 
},
 
},
 
axis =
 
axis =
 
{
 
{
stroke = { value = "#54595d" },
+
stroke = { value = persistentGrey },
 
strokeWidth = { value = 2 }
 
strokeWidth = { value = 2 }
 
},
 
},
 
grid =
 
grid =
 
{
 
{
stroke = { value = "#54595d" }
+
stroke = { value = persistentGrey }
 
}
 
}
 
}
 
}
 +
 
end
 
end
   Line 777: Line 914:  
stroke = "color",
 
stroke = "color",
 
title = legendTitle,
 
title = legendTitle,
 +
}
 +
legend.properties = {
 +
title = {
 +
fill = { value = persistentGrey },
 +
},
 +
labels = {
 +
fill = { value = persistentGrey },
 +
},
 
}
 
}
 
if chartType == "pie" then
 
if chartType == "pie" then
-- move legend from center position to top
+
legend.properties = {
legend.properties = { legend = { y = { value = -outerRadius } } }
+
-- move legend from center position to top
 +
legend = {
 +
y = { value = -outerRadius },
 +
},
 +
title = {
 +
fill = { value = persistentGrey }
 +
},
 +
labels = {
 +
fill = { value = persistentGrey },
 +
},
 +
}
 
end
 
end
 
return legend
 
return legend
Line 799: Line 954:  
-- for line charts, the thickness of the line; for pie charts the gap between each slice
 
-- for line charts, the thickness of the line; for pie charts the gap between each slice
 
local linewidth = tonumber(frame.args.linewidth)
 
local linewidth = tonumber(frame.args.linewidth)
 +
local linewidthsString = frame.args.linewidths
 +
local linewidths
 +
if linewidthsString and linewidthsString ~= "" then linewidths = numericArray(linewidthsString) or false end
 
-- x and y axis caption
 
-- x and y axis caption
local xTitle = frame.args.xAxisTitle
+
local xTitle = frame.args.xAxisTitle or frame.args.xaxistitle
local yTitle = frame.args.yAxisTitle
+
local yTitle = frame.args.yAxisTitle or frame.args.yaxistitle
 
-- x and y value types
 
-- x and y value types
local xType = frame.args.xType
+
local xType = frame.args.xType or frame.args.xtype
local yType = frame.args.yType
+
local yType = frame.args.yType or frame.args.ytype
 
-- override x and y axis minimum and maximum
 
-- override x and y axis minimum and maximum
local xMin = frame.args.xAxisMin
+
local xMin = frame.args.xAxisMin or frame.args.xaxismin
local xMax = frame.args.xAxisMax
+
local xMax = frame.args.xAxisMax or frame.args.xaxismax
local yMin = frame.args.yAxisMin
+
local yMin = frame.args.yAxisMin or frame.args.yaxismin
local yMax = frame.args.yAxisMax
+
local yMax = frame.args.yAxisMax or frame.args.yaxismax
 
-- override x and y axis label formatting
 
-- override x and y axis label formatting
local xAxisFormat = frame.args.xAxisFormat
+
local xAxisFormat = frame.args.xAxisFormat or frame.args.xaxisformat
local yAxisFormat = frame.args.yAxisFormat
+
local yAxisFormat = frame.args.yAxisFormat or frame.args.yaxisformat
local xAxisAngle = tonumber(frame.args.xAxisAngle)
+
local xAxisAngle = tonumber(frame.args.xAxisAngle) or tonumber(frame.args.xaxisangle)
 +
-- x and y scale types
 +
local xScaleType = frame.args.xScaleType or frame.args.xscaletype
 +
local yScaleType = frame.args.yScaleType or frame.args.yscaletype 
 +
-- log scale require minimum > 0, for now it's no possible to plot negative values on log - TODO see: https://www.mathworks.com/matlabcentral/answers/1792-log-scale-graphic-with-negative-value
 +
-- if xScaleType == "log" then
 +
-- if (not xMin or tonumber(xMin) <= 0) then xMin = 0.1 end
 +
-- if not xType then xType = "number" end
 +
-- end
 +
-- if yScaleType == "log" then
 +
-- if (not yMin or tonumber(yMin) <= 0) then yMin = 0.1 end
 +
-- if not yType then yType = "number" end
 +
-- end
 +
 
 +
 +
 
 
-- show grid
 
-- show grid
local xGrid = frame.args.xGrid or "0"
+
local xGrid = frame.args.xGrid or frame.args.xgrid or false
local yGrid = frame.args.yGrid or "0"
+
local yGrid = frame.args.yGrid or frame.args.ygrid or false
 
-- for line chart, show a symbol at each data point
 
-- for line chart, show a symbol at each data point
local showSymbols = frame.args.showSymbols
+
local showSymbols = frame.args.showSymbols or frame.args.showsymbols
 +
local symbolsShape = frame.args.symbolsShape or frame.args.symbolsshape
 +
local symbolsNoFill = frame.args.symbolsNoFill or frame.args.symbolsnofill
 +
local symbolsStroke = tonumber(frame.args.symbolsStroke or frame.args.symbolsstroke)
 
-- show legend with given title
 
-- show legend with given title
 
local legendTitle = frame.args.legend
 
local legendTitle = frame.args.legend
 
-- show values as text
 
-- show values as text
local showValues = frame.args.showValues
+
local showValues = frame.args.showValues or frame.args.showvalues
 
-- pie chart radiuses
 
-- pie chart radiuses
local innerRadius = tonumber(frame.args.innerRadius) or 0
+
local innerRadius = tonumber(frame.args.innerRadius) or tonumber(frame.args.innerradius) or 0
 
local outerRadius = math.min(graphwidth, graphheight)
 
local outerRadius = math.min(graphwidth, graphheight)
 
-- format JSON output
 
-- format JSON output
Line 842: Line 1,018:  
yValues[yNum] = value
 
yValues[yNum] = value
 
-- name the series: default is "y<number>". Can be overwritten using the "y<number>Title" parameters.
 
-- name the series: default is "y<number>". Can be overwritten using the "y<number>Title" parameters.
seriesTitles[yNum] = frame.args["y" .. yNum .. "Title"] or name
+
seriesTitles[yNum] = frame.args["y" .. yNum .. "Title"] or frame.args["y" .. yNum .. "title"] or name
 
end
 
end
 
end
 
end
Line 882: Line 1,058:  
local scales = {}
 
local scales = {}
   −
local xscale = getXScale(chartType, stacked, xMin, xMax, xType)
+
local xscale = getXScale(chartType, stacked, xMin, xMax, xType, xScaleType)
 
table.insert(scales, xscale)
 
table.insert(scales, xscale)
local yscale = getYScale(chartType, stacked, yMin, yMax, yType)
+
local yscale = getYScale(chartType, stacked, yMin, yMax, yType, yScaleType)
 
table.insert(scales, yscale)
 
table.insert(scales, yscale)
   Line 892: Line 1,068:  
local alphaScale = getAlphaColorScale(colors, y)
 
local alphaScale = getAlphaColorScale(colors, y)
 
table.insert(scales, alphaScale)
 
table.insert(scales, alphaScale)
 +
 +
local lineScale
 +
if (linewidths) and (chartType == "line") then
 +
lineScale = getLineScale(linewidths, chartType)
 +
table.insert(scales, lineScale)
 +
end
    
local radiusScale
 
local radiusScale
Line 904: Line 1,086:     
-- create chart markings
 
-- create chart markings
local chartvis = getChartVisualisation(chartType, stacked, colorField, #y, innerRadius, outerRadius, linewidth, alphaScale, radiusScale, interpolate)
+
local chartvis = getChartVisualisation(chartType, stacked, colorField, #y, innerRadius, outerRadius, linewidth, alphaScale, radiusScale, lineScale, interpolate)
 
local marks = { chartvis }
 
local marks = { chartvis }
 
 
Line 927: Line 1,109:  
end
 
end
 
end
 
end
 
+
 +
    -- grids
 +
    if xGrid then
 +
    if xGrid == "0" then xGrid = false
 +
    elseif xGrid == 0 then xGrid = false
 +
    elseif xGrid == "false" then xGrid = false
 +
    elseif xGrid == "n" then xGrid = false
 +
    else xGrid = true
 +
    end
 +
    end
 +
    if yGrid then
 +
    if yGrid == "0" then yGrid = false
 +
    elseif yGrid == 0 then yGrid = false
 +
    elseif yGrid == "false" then yGrid = false
 +
    elseif yGrid == "n" then yGrid = false
 +
    else yGrid = true
 +
    end
 +
    end
 +
   
 
-- symbol marks
 
-- symbol marks
if chartType == "line" and showSymbols then
+
if showSymbols  and chartType ~= "rect" then
 
local chartmarks = chartvis
 
local chartmarks = chartvis
 
if chartmarks.marks then chartmarks = chartmarks.marks[1] end
 
if chartmarks.marks then chartmarks = chartmarks.marks[1] end
local symbolmarks = getSymbolMarks(chartmarks)
+
 
 +
if type(showSymbols) == "string" then
 +
if showSymbols == "" then showSymbols = true
 +
else showSymbols = numericArray(showSymbols)
 +
end
 +
else
 +
showSymbols = tonumber(showSymbols)
 +
end
 +
 
 +
-- custom size
 +
local symSize
 +
if type(showSymbols) == "number" then
 +
symSize = tonumber(showSymbols*showSymbols*8.5)
 +
elseif type(showSymbols) == "table" then
 +
symSize = {}
 +
for k, v in pairs(showSymbols) do
 +
                symSize[k]=v*v*8.5 -- "size" acc to Vega syntax is area of symbol
 +
            end
 +
        else
 +
symSize = 50
 +
end
 +
-- symSizeScale
 +
local symSizeScale = {}
 +
if type(symSize) == "table" then
 +
symSizeScale = getSymSizeScale(symSize)
 +
table.insert(scales, symSizeScale)
 +
end
 +
 +
 
 +
    -- custom shape
 +
    if  stringArray(symbolsShape) and #stringArray(symbolsShape) > 1 then symbolsShape = stringArray(symbolsShape) end
 +
   
 +
    local symShape = " "
 +
 +
if type(symbolsShape) == "string" and shapes[symbolsShape] then
 +
symShape = shapes[symbolsShape]
 +
elseif type(symbolsShape) == "table" then
 +
symShape = {}
 +
for k, v in pairs(symbolsShape) do
 +
                if symbolsShape[k] and shapes[symbolsShape[k]] then
 +
                symShape[k]=shapes[symbolsShape[k]]
 +
                else
 +
                symShape[k] = "circle"
 +
                end
 +
            end
 +
      else
 +
symShape = "circle"
 +
end
 +
-- symShapeScale
 +
local symShapeScale = {}
 +
if type(symShape) == "table" then
 +
symShapeScale = getSymShapeScale(symShape)
 +
table.insert(scales, symShapeScale)
 +
end
 +
 +
-- custom stroke
 +
local symStroke
 +
if (type(symbolsStroke) == "number") then
 +
symStroke = tonumber(symbolsStroke)
 +
-- TODO symStroke serialization
 +
-- elseif type(symbolsStroke) == "table" then
 +
-- symStroke = {}
 +
-- for k, v in pairs(symbolsStroke) do
 +
--                symStroke[k]=symbolsStroke[k]
 +
--                --always draw x with stroke
 +
-- if symbolsShape[k] == "x" then symStroke[k] = 2.5 end
 +
--always draw x with stroke
 +
-- if symbolsNoFill[k] then symStroke[k] = 2.5 end
 +
--            end
 +
else
 +
symStroke = 0
 +
--always draw x with stroke
 +
if symbolsShape == "x" then symStroke = 2.5 end
 +
--always draw x with stroke
 +
if symbolsNoFill then symStroke = 2.5 end
 +
end
 +
 
 +
 
 +
-- TODO -- symStrokeScale
 +
-- local symStrokeScale = {}
 +
-- if type(symStroke) == "table" then
 +
-- symStrokeScale = getSymStrokeScale(symStroke)
 +
-- table.insert(scales, symStrokeScale)
 +
-- end
 +
 
 +
 
 +
 +
local symbolmarks = getSymbolMarks(chartmarks, symSize, symShape, symStroke, symbolsNoFill, alphaScale)
 
if chartmarks ~= chartvis then
 
if chartmarks ~= chartvis then
 
table.insert(chartvis.marks, symbolmarks)
 
table.insert(chartvis.marks, symbolmarks)
Line 942: Line 1,229:  
-- axes
 
-- axes
 
local xAxis, yAxis = getAxes(xTitle, xAxisFormat, xAxisAngle, xType, xGrid, yTitle, yAxisFormat, yType, yGrid, chartType)
 
local xAxis, yAxis = getAxes(xTitle, xAxisFormat, xAxisAngle, xType, xGrid, yTitle, yAxisFormat, yType, yGrid, chartType)
 
+
 
-- legend
 
-- legend
 
local legend
 
local legend
 
if legendTitle and tonumber(legendTitle) ~= 0 then legend = getLegend(legendTitle, chartType, outerRadius) end
 
if legendTitle and tonumber(legendTitle) ~= 0 then legend = getLegend(legendTitle, chartType, outerRadius) end
   
-- construct final output object
 
-- construct final output object
 
local output =
 
local output =
Line 972: Line 1,258:  
return p.chart(frame:getParent())
 
return p.chart(frame:getParent())
 
end
 
end
 +
 +
function p.chartDebuger(frame)
 +
return  "\n\nchart JSON\n ".. p.chart(frame) .. " \n\n" .. debuglog
 +
end
 +
    
-- Given an HTML-encoded title as first argument, e.g. one produced with {{ARTICLEPAGENAME}},
 
-- Given an HTML-encoded title as first argument, e.g. one produced with {{ARTICLEPAGENAME}},
Anonymous user