Modul:Graph – Wikipedia
Zum Inhalt springen
aus Wikipedia, der freien Enzyklopädie
Vorlagenprogrammierung
Diskussionen
Lua
Unterseiten
Modul
Modul:
Dokumentation
Diese Seite enthält Code in der
Programmiersprache Lua
Einbindungszahl
Cirrus
Dies ist die (produktive)
Mutterversion
eines global benutzten Lua-Moduls.
Wenn die
serial
-Information nicht übereinstimmt, müsste eine Kopie hiervon in das lokale Wiki geschrieben werden.
Versionsbezeichnung auf WikiData:
2020-09-01
-- 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
-- Reordering even strings like integers - see https://en.wikipedia.org/wiki/Template_talk:Graph:Chart#Reordering_even_strings_like_integers
-- TODO:
-- marks:
-- - line strokeDash + serialization,
-- - symStroke serialization
-- - symbolsNoFill serialization
-- - arbitrary SVG path symbol shape as symbolsShape argument
-- - annotations
-- - vertical / horizontal line at specific values [DONE] 2020-09-01
-- - 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_):
-- 2020-09-01 Vertical and horizontal line annotations
-- 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
-- 2018-10-13 Fix browser color-inversion issues via #54595d per [[mw:Template:Graph:PageViews]]
-- 2018-09-16 Allow disabling the legend for templates
-- 2018-09-10 Allow grid lines
-- 2018-08-26 Use user-defined order for stacked charts
-- 2018-02-11 Force usage of explicitely provided x minimum and/or maximum values, rotation of x labels
-- 2017-08-08 Added showSymbols param to show symbols on line charts
-- 2016-05-16 Added encodeTitleForPath() to help all path-based APIs graphs like pageviews
-- 2016-03-20 Allow omitted data for charts, labels for line charts with string (ordinal) scale at point location
-- 2016-01-28 For maps, always use wikiraw:// protocol. https:// will be disabled soon.
local
{}
--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
local
debuglog
"Debug "
..
\n\n
local
baseMapDirectory
"Module:Graph/"
local
persistentGrey
"#54595d"
local
shapes
{}
shapes
circle
"circle"
"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
if
not
csv
then
return
end
local
list
mw
text
split
csv
"%s*,%s*"
local
result
{}
local
isInteger
true
for
list
do
if
list
==
""
then
result
nil
else
result
tonumber
list
])
if
not
result
then
return
end
if
isInteger
then
local
int
frac
math.modf
result
])
isInteger
frac
==
0.0
end
end
end
return
result
isInteger
end
local
function
stringArray
text
if
not
text
then
return
end
local
list
mw
text
split
mw
ustring
gsub
tostring
text
),
\\
,"
""
),
","
true
for
list
do
list
mw
ustring
gsub
mw
text
trim
list
]),
""
","
end
return
list
end
local
function
isTable
return
type
==
"table"
end
local
function
copy
if
type
==
"table"
then
local
result
{}
for
key
value
in
pairs
do
result
key
copy
value
end
return
result
else
return
end
end
function
map
frame
-- map path data for geographic objects
local
basemap
frame
args
basemap
or
"WorldMap-iso2.json"
-- WorldMap name and/or location may vary from wiki to wiki
-- scaling factor
local
scale
tonumber
frame
args
scale
or
100
-- map projection, see https://github.com/mbostock/d3/wiki/Geo-Projections
local
projection
frame
args
projection
or
"equirectangular"
-- defaultValue for geographic objects without data
local
defaultValue
frame
args
defaultValue
or
frame
args
defaultvalue
local
scaleType
frame
args
scaleType
or
frame
args
scaletype
or
"linear"
-- minimaler Wertebereich (nur für numerische Daten)
local
domainMin
tonumber
frame
args
domainMin
or
frame
args
domainmin
-- maximaler Wertebereich (nur für numerische Daten)
local
domainMax
tonumber
frame
args
domainMax
or
frame
args
domainmax
-- Farbwerte der Farbskala (nur für numerische Daten)
local
colorScale
frame
args
colorScale
or
frame
args
colorscale
or
"category10"
-- show 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
local
formatJson
frame
args
formatjson
-- map data are key-value pairs: keys are non-lowercase strings (ideally ISO codes) which need to match the "id" values of the map path data
local
values
{}
local
isNumbers
nil
for
name
value
in
pairs
frame
args
do
if
mw
ustring
find
name
"^[^%l]+$"
and
value
and
value
~=
""
then
if
isNumbers
==
nil
then
isNumbers
tonumber
value
end
local
data
id
name
value
if
isNumbers
then
data
tonumber
data
end
table.insert
values
data
end
end
if
not
defaultValue
then
if
isNumbers
then
defaultValue
else
defaultValue
"silver"
end
end
-- create highlight scale
local
scales
if
isNumbers
then
if
colorScale
then
colorScale
string.lower
colorScale
end
if
colorScale
==
"category10"
or
colorScale
==
"category20"
then
else
colorScale
stringArray
colorScale
end
scales
name
"color"
type
scaleType
domain
data
"highlights"
field
"v"
},
range
colorScale
nice
true
zero
false
if
domainMin
then
scales
].
domainMin
domainMin
end
if
domainMax
then
scales
].
domainMax
domainMax
end
local
exponent
string.match
scaleType
"pow%s+(%d+%.?%d+)"
-- check for exponent
if
exponent
then
scales
].
type
"pow"
scales
].
exponent
exponent
end
end
-- create legend
if
legend
then
legend
fill
"color"
offset
120
properties
title
fontSize
value
14
},
labels
fontSize
value
12
},
legend
stroke
value
"silver"
},
strokeWidth
value
1.5
end
-- get map url
local
basemapUrl
if
string.sub
basemap
10
==
"wikiraw://"
then
basemapUrl
basemap
else
-- if not a (supported) url look for a colon as namespace separator. If none prepend default map directory name.
if
not
string.find
basemap
":"
then
basemap
baseMapDirectory
..
basemap
end
basemapUrl
"wikiraw:///"
..
mw
uri
encode
mw
title
new
basemap
).
prefixedText
"PATH"
end
local
output
version
width
-- generic value as output size depends solely on map size and scaling factor
height
-- ditto
data
-- data source for the highlights
name
"highlights"
values
values
},
-- data source for map paths data
name
feature
url
basemapUrl
format
type
"topojson"
feature
feature
},
transform
-- geographic transformation ("geopath") of map paths data
type
"geopath"
value
"data"
-- data source
scale
scale
translate
},
center
center
projection
projection
},
-- join ("zip") of mutiple data source: here map paths data and highlights
type
"lookup"
keys
"id"
},
-- key for map paths data
on
"highlights"
-- name of highlight data source
onKey
"id"
-- key for highlight data source
as
"zipped"
},
-- name of resulting table
default
defaultValue
-- default value for geographic objects that could not be joined
},
marks
-- output markings (map paths and highlights)
type
"path"
from
data
feature
},
properties
enter
path
field
"layout_path"
},
update
fill
field
"zipped.v"
},
hover
fill
value
"darkgrey"
},
legends
legend
if
scales
then
output
scales
scales
output
marks
].
properties
update
fill
scale
"color"
end
local
flags
if
formatJson
then
flags
mw
text
JSON_PRETTY
end
return
mw
text
jsonEncode
output
flags
end
local
function
deserializeXData
serializedX
xType
xMin
xMax
local
if
not
xType
or
xType
==
"integer"
or
xType
==
"number"
then
local
isInteger
isInteger
numericArray
serializedX
if
then
xMin
tonumber
xMin
xMax
tonumber
xMax
if
not
xType
then
if
isInteger
then
xType
"integer"
else
xType
"number"
end
end
else
if
xType
then
error
"Numbers expected for parameter 'x'"
end
end
end
if
not
then
stringArray
serializedX
if
not
xType
then
xType
"string"
end
end
return
xType
xMin
xMax
end
local
function
deserializeYData
serializedYs
yType
yMin
yMax
local
{}
local
areAllInteger
true
for
yNum
value
in
pairs
serializedYs
do
local
yValues
if
not
yType
or
yType
==
"integer"
or
yType
==
"number"
then
local
isInteger
yValues
isInteger
numericArray
value
if
yValues
then
areAllInteger
areAllInteger
and
isInteger
else
if
yType
then
error
"Numbers expected for parameter '"
..
name
..
"'"
else
return
deserializeYData
serializedYs
"string"
yMin
yMax
end
end
end
if
not
yValues
then
yValues
stringArray
value
end
yNum
yValues
end
if
not
yType
then
if
areAllInteger
then
yType
"integer"
else
yType
"number"
end
end
if
yType
==
"integer"
or
yType
==
"number"
then
yMin
tonumber
yMin
yMax
tonumber
yMax
end
return
yType
yMin
yMax
end
local
function
convertXYToManySeries
xType
yType
seriesTitles
local
data
name
"chart"
format
type
"json"
parse
xType
yType
},
values
{}
for
do
local
yLen
table
maxn
])
for
do
if
<=
yLen
and
][
then
table.insert
data
values
series
seriesTitles
],
],
][
})
end
end
end
return
data
end
local
function
convertXYToSingleSeries
xType
yType
yNames
local
data
name
"chart"
format
type
"json"
parse
xType
},
values
{}
for
do
data
format
parse
yNames
]]
yType
end
for
do
local
item
for
do
item
yNames
]]
][
end
table.insert
data
values
item
end
return
data
end
local
function
getXScale
chartType
stacked
xMin
xMax
xType
xScaleType
if
chartType
==
"pie"
then
return
end
local
xscale
name
"x"
range
"width"
zero
false
-- do not include zero value
domain
data
"chart"
field
"x"
if
xScaleType
then
xscale
type
xScaleType
else
xscale
type
"linear"
end
if
xMin
then
xscale
domainMin
xMin
end
if
xMax
then
xscale
domainMax
xMax
end
if
xMin
or
xMax
then
xscale
clamp
true
xscale
nice
false
end
if
chartType
==
"rect"
then
xscale
type
"ordinal"
if
not
stacked
then
xscale
padding
0.2
end
-- pad each bar group
else
if
xType
==
"date"
then
xscale
type
"time"
elseif
xType
==
"string"
then
xscale
type
"ordinal"
xscale
points
true
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
end
local
function
getYScale
chartType
stacked
yMin
yMax
yType
yScaleType
if
chartType
==
"pie"
then
return
end
local
yscale
name
"y"
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
zero
chartType
~=
"line"
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
yMax
then
yscale
domainMax
yMax
end
if
yMin
or
yMax
then
yscale
clamp
true
end
if
yType
==
"date"
then
yscale
type
"time"
elseif
yType
==
"string"
then
yscale
type
"ordinal"
end
if
stacked
then
yscale
domain
data
"stats"
field
"sum_y"
else
yscale
domain
data
"chart"
field
"y"
end
return
yscale
end
local
function
getColorScale
colors
chartType
xCount
yCount
if
not
colors
then
if
chartType
==
"pie"
and
xCount
10
or
yCount
10
then
colors
"category20"
else
colors
"category10"
end
end
local
colorScale
name
"color"
type
"ordinal"
range
colors
domain
data
"chart"
field
"series"
if
chartType
==
"pie"
then
colorScale
domain
field
"x"
end
return
colorScale
end
local
function
getAlphaColorScale
colors
local
alphaScale
-- if there is at least one color in the format "#aarrggbb", create a transparency (alpha) scale
if
isTable
colors
then
local
alphas
{}
local
hasAlpha
false
for
colors
do
local
rgb
string.match
colors
],
"#(%x%x)(%x%x%x%x%x%x)"
if
then
hasAlpha
true
alphas
tostring
tonumber
16
255.0
colors
"#"
..
rgb
else
alphas
"1"
end
end
for
colors
do
alphas
"1"
end
if
hasAlpha
then
alphaScale
name
"transparency"
type
"ordinal"
range
alphas
end
end
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
local
function
getValueScale
fieldName
min
max
type
local
valueScale
name
fieldName
type
type
or
"linear"
domain
data
"chart"
field
fieldName
},
range
min
max
return
valueScale
end
local
function
addInteractionToChartVisualisation
plotMarks
colorField
dataField
-- initial setup
if
not
plotMarks
properties
enter
then
plotMarks
properties
enter
{}
end
plotMarks
properties
enter
colorField
scale
"color"
field
dataField
-- action when cursor is over plot mark: highlight
if
not
plotMarks
properties
hover
then
plotMarks
properties
hover
{}
end
plotMarks
properties
hover
colorField
value
"red"
-- action when cursor leaves plot mark: reset to initial setup
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
linecolor
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
linecolor
or
"white"
},
strokeWidth
value
linewidth
or
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
linecolor
alphaScale
radiusScale
lineScale
interpolate
if
chartType
==
"pie"
then
return
getPieChartVisualisation
yCount
innerRadius
outerRadius
linewidth
linecolor
radiusScale
end
local
chartvis
type
chartType
properties
-- chart creation event handler
enter
scale
"x"
field
"x"
},
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
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
-- 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
then
chartvis
properties
enter
scale
"series"
chartvis
properties
enter
field
"series"
chartvis
properties
enter
width
scale
"series"
end
end
-- stacked charts have their own (stacked) y values
if
stacked
then
chartvis
properties
enter
field
"layout_start"
end
-- if there are multiple series group these together
if
yCount
==
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
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
].
groupby
"x"
chartvis
scales
groupScale
chartvis
properties
enter
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
scale
chartvis
properties
enter
scale
field
chartvis
properties
enter
field
},
scale
chartvis
properties
enter
scale
field
chartvis
properties
enter
field
offset
tonumber
showValues
offset
or
},
--dx = { scale = chartvis.properties.enter.x.scale, band = true, mult = 0.5 }, -- for horizontal text
dy
scale
chartvis
properties
enter
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
offset
>=
then
properties
align
value
"right"
properties
fill
value
showValues
fontcolor
or
"white"
else
properties
align
value
"left"
properties
fill
value
showValues
fontcolor
or
persistentGrey
end
elseif
chartType
==
"pie"
then
properties
group
"width"
mult
0.5
},
group
"height"
mult
0.5
},
radius
offset
tonumber
showValues
offset
or
},
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
"center"
properties
angle
field
"layout_mid"
mult
180.0
math.pi
if
properties
radius
offset
>=
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 left on right half-circle and right on left half-circle
local
alignScale
name
"align"
type
"quantize"
domainMin
0.0
domainMax
math.pi
range
"left"
"right"
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
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
"{{"
..
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
scale
"x"
field
"x"
},
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
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
return
symbolmarks
end
local
function
getAnnoMarks
chartvis
stroke
fill
opacity
local
vannolines
hannolines
vannoLabels
vannoLabels
vannolines
type
"rule"
from
data
"v_anno"
},
properties
update
scale
"x"
field
"x"
},
value
},
y2
field
group
"height"
},
strokeWidth
value
stroke
},
stroke
value
persistentGrey
},
opacity
value
opacity
vannolabels
type
"text"
from
data
"v_anno"
},
properties
update
scale
"x"
field
"x"
offset
},
field
group
"height"
},
offset
},
text
field
"label"
},
baseline
value
"top"
},
angle
value
90
},
fill
value
persistentGrey
},
opacity
value
opacity
hannolines
type
"rule"
from
data
"h_anno"
},
properties
update
scale
"y"
field
"y"
},
value
},
x2
field
group
"width"
},
strokeWidth
value
stroke
},
stroke
value
persistentGrey
},
opacity
value
opacity
hannolabels
type
"text"
from
data
"h_anno"
},
properties
update
scale
"y"
field
"y"
offset
},
value
offset
},
text
field
"label"
},
baseline
value
"top"
},
angle
value
},
fill
value
persistentGrey
},
opacity
value
opacity
return
vannolines
vannolabels
hannolines
hannolabels
end
local
function
getAxes
xTitle
xAxisFormat
xAxisAngle
xType
xGrid
yTitle
yAxisFormat
yType
yGrid
chartType
local
xAxis
yAxis
if
chartType
~=
"pie"
then
if
xType
==
"integer"
and
not
xAxisFormat
then
xAxisFormat
"d"
end
xAxis
type
"x"
scale
"x"
title
xTitle
format
xAxisFormat
grid
xGrid
if
xAxisAngle
then
local
xAxisAlign
if
xAxisAngle
then
xAxisAlign
"right"
else
xAxisAlign
"left"
end
xAxis
properties
title
fill
value
persistentGrey
},
labels
angle
value
xAxisAngle
},
align
value
xAxisAlign
},
fill
value
persistentGrey
},
ticks
stroke
value
persistentGrey
},
axis
stroke
value
persistentGrey
},
strokeWidth
value
},
grid
stroke
value
persistentGrey
else
xAxis
properties
title
fill
value
persistentGrey
},
labels
fill
value
persistentGrey
},
ticks
stroke
value
persistentGrey
},
axis
stroke
value
persistentGrey
},
strokeWidth
value
},
grid
stroke
value
persistentGrey
end
if
yType
==
"integer"
and
not
yAxisFormat
then
yAxisFormat
"d"
end
yAxis
type
"y"
scale
"y"
title
yTitle
format
yAxisFormat
grid
yGrid
yAxis
properties
title
fill
value
persistentGrey
},
labels
fill
value
persistentGrey
},
ticks
stroke
value
persistentGrey
},
axis
stroke
value
persistentGrey
},
strokeWidth
value
},
grid
stroke
value
persistentGrey
end
return
xAxis
yAxis
end
local
function
getLegend
legendTitle
chartType
outerRadius
local
legend
fill
"color"
stroke
"color"
title
legendTitle
legend
properties
title
fill
value
persistentGrey
},
},
labels
fill
value
persistentGrey
},
},
if
chartType
==
"pie"
then
legend
properties
-- move legend from center position to top
legend
value
outerRadius
},
},
title
fill
value
persistentGrey
},
labels
fill
value
persistentGrey
},
},
end
return
legend
end
function
chart
frame
-- chart width and height
local
graphwidth
tonumber
frame
args
width
or
200
local
graphheight
tonumber
frame
args
height
or
200
-- chart type
local
chartType
frame
args
type
or
"line"
-- interpolation mode for line and area charts: linear, step-before, step-after, basis, basis-open, basis-closed (type=line only), bundle (type=line only), cardinal, cardinal-open, cardinal-closed (type=line only), monotone
local
interpolate
frame
args
interpolate
-- mark colors (if no colors are given, the default 10 color palette is used)
local
colorString
frame
args
colors
if
colorString
then
colorString
string.lower
colorString
end
local
colors
stringArray
colorString
-- for line charts, the thickness of the line; for pie charts the gap between each slice
local
linewidth
tonumber
frame
args
linewidth
local
linewidthsString
frame
args
linewidths
local
linewidths
if
linewidthsString
and
linewidthsString
~=
""
then
linewidths
numericArray
linewidthsString
or
false
end
local
linecolor
frame
args
linecolor
or
'white'
-- x and y axis caption
local
xTitle
frame
args
xAxisTitle
or
frame
args
xaxistitle
local
yTitle
frame
args
yAxisTitle
or
frame
args
yaxistitle
-- x and y value types
local
xType
frame
args
xType
or
frame
args
xtype
local
yType
frame
args
yType
or
frame
args
ytype
-- override x and y axis minimum and maximum
local
xMin
frame
args
xAxisMin
or
frame
args
xaxismin
local
xMax
frame
args
xAxisMax
or
frame
args
xaxismax
local
yMin
frame
args
yAxisMin
or
frame
args
yaxismin
local
yMax
frame
args
yAxisMax
or
frame
args
yaxismax
-- override x and y axis label formatting
local
xAxisFormat
frame
args
xAxisFormat
or
frame
args
xaxisformat
local
yAxisFormat
frame
args
yAxisFormat
or
frame
args
yaxisformat
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
local
xGrid
frame
args
xGrid
or
frame
args
xgrid
or
false
local
yGrid
frame
args
yGrid
or
frame
args
ygrid
or
false
-- for line chart, show a symbol at each data point
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
local
legendTitle
frame
args
legend
-- show values as text
local
showValues
frame
args
showValues
or
frame
args
showvalues
-- show v- and h-line annotations
local
v_annoLineString
frame
args
vAnnotatonsLine
or
frame
args
vannotatonsline
local
h_annoLineString
frame
args
hAnnotatonsLine
or
frame
args
hannotatonsline
local
v_annoLabelString
frame
args
vAnnotatonsLabel
or
frame
args
vannotatonslabel
local
h_annoLabelString
frame
args
hAnnotatonsLabel
or
frame
args
hannotatonslabel
-- decode annotations cvs
local
v_annoLine
v_annoLabel
h_annoLine
h_annoLabel
if
v_annoLineString
and
v_annoLineString
~=
""
then
if
xType
==
"number"
or
xType
==
"integer"
then
v_annoLine
numericArray
v_annoLineString
else
v_annoLine
stringArray
v_annoLineString
end
v_annoLabel
stringArray
v_annoLabelString
end
if
h_annoLineString
and
h_annoLineString
~=
""
then
if
yType
==
"number"
or
yType
==
"integer"
then
h_annoLine
numericArray
h_annoLineString
else
h_annoLine
stringArray
h_annoLineString
end
h_annoLabel
stringArray
h_annoLabelString
end
-- pie chart radiuses
local
innerRadius
tonumber
frame
args
innerRadius
or
tonumber
frame
args
innerradius
or
local
outerRadius
math.min
graphwidth
graphheight
-- format JSON output
local
formatJson
frame
args
formatjson
-- get x values
local
xType
xMin
xMax
deserializeXData
frame
args
xType
xMin
xMax
-- get y values (series)
local
yValues
{}
local
seriesTitles
{}
for
name
value
in
pairs
frame
args
do
local
yNum
if
name
==
"y"
then
yNum
else
yNum
tonumber
string.match
name
"^y(%d+)$"
))
end
if
yNum
then
yValues
yNum
value
-- name the series: default is "y". Can be overwritten using the "yTitle" parameters.
seriesTitles
yNum
frame
args
"y"
..
yNum
..
"Title"
or
frame
args
"y"
..
yNum
..
"title"
or
name
end
end
local
yType
yMin
yMax
deserializeYData
yValues
yType
yMin
yMax
-- create data tuples, consisting of series index, x value, y value
local
data
if
chartType
==
"pie"
then
-- for pie charts the second second series is merged into the first series as radius values
data
convertXYToSingleSeries
xType
yType
"y"
"r"
})
else
data
convertXYToManySeries
xType
yType
seriesTitles
end
-- configure stacked charts
local
stacked
false
local
stats
if
string.sub
chartType
==
"stacked"
then
chartType
string.sub
chartType
if
then
-- ignore stacked charts if there is only one series
stacked
true
-- aggregate data by cumulative y values
stats
name
"stats"
source
"chart"
transform
type
"aggregate"
groupby
"x"
},
summarize
"sum"
end
end
-- add annotations to data
local
vannoData
hannoData
if
v_annoLine
then
vannoData
name
"v_anno"
format
type
"json"
parse
xType
},
values
{}
for
v_annoLine
do
local
item
v_annoLine
],
label
v_annoLabel
table.insert
vannoData
values
item
end
end
if
h_annoLine
then
hannoData
name
"h_anno"
format
type
"json"
parse
yType
},
values
{}
for
h_annoLine
do
local
item
h_annoLine
],
label
h_annoLabel
table.insert
hannoData
values
item
end
end
-- create scales
local
scales
{}
local
xscale
getXScale
chartType
stacked
xMin
xMax
xType
xScaleType
table.insert
scales
xscale
local
yscale
getYScale
chartType
stacked
yMin
yMax
yType
yScaleType
table.insert
scales
yscale
local
colorScale
getColorScale
colors
chartType
table.insert
scales
colorScale
local
alphaScale
getAlphaColorScale
colors
table.insert
scales
alphaScale
local
lineScale
if
linewidths
and
chartType
==
"line"
then
lineScale
getLineScale
linewidths
chartType
table.insert
scales
lineScale
end
local
radiusScale
if
chartType
==
"pie"
and
then
radiusScale
getValueScale
"r"
outerRadius
table.insert
scales
radiusScale
end
-- decide if lines (strokes) or areas (fills) should be drawn
local
colorField
if
chartType
==
"line"
then
colorField
"stroke"
else
colorField
"fill"
end
-- create chart markings
local
chartvis
getChartVisualisation
chartType
stacked
colorField
innerRadius
outerRadius
linewidth
linecolor
alphaScale
radiusScale
lineScale
interpolate
local
marks
chartvis
-- text marks
if
showValues
then
if
type
showValues
==
"string"
then
-- deserialize as table
local
keyValues
mw
text
split
showValues
"%s*,%s*"
showValues
{}
for
kv
in
ipairs
keyValues
do
local
key
value
mw
ustring
match
kv
"^%s*(.-)%s*:%s*(.-)%s*$"
if
key
then
showValues
key
value
end
end
end
local
chartmarks
chartvis
if
chartmarks
marks
then
chartmarks
chartmarks
marks
end
local
textmarks
getTextMarks
chartmarks
chartType
outerRadius
scales
radiusScale
yType
showValues
if
chartmarks
~=
chartvis
then
table.insert
chartvis
marks
textmarks
else
table.insert
marks
textmarks
end
end
-- grids
if
xGrid
then
if
xGrid
==
"0"
then
xGrid
false
elseif
xGrid
==
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
==
then
yGrid
false
elseif
yGrid
==
"false"
then
yGrid
false
elseif
yGrid
==
"n"
then
yGrid
false
else
yGrid
true
end
end
-- symbol marks
if
showSymbols
and
chartType
~=
"rect"
then
local
chartmarks
chartvis
if
chartmarks
marks
then
chartmarks
chartmarks
marks
end
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
in
pairs
showSymbols
do
symSize
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
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
in
pairs
symbolsShape
do
if
symbolsShape
and
shapes
symbolsShape
]]
then
symShape
shapes
symbolsShape
]]
else
symShape
"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
--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
table.insert
chartvis
marks
symbolmarks
else
table.insert
marks
symbolmarks
end
end
local
vannolines
vannolabels
hannolines
hannolabels
getAnnoMarks
chartmarks
persistentGrey
persistentGrey
0.75
if
vannoData
then
table.insert
marks
vannolines
table.insert
marks
vannolabels
end
if
hannoData
then
table.insert
marks
hannolines
table.insert
marks
hannolabels
end
-- axes
local
xAxis
yAxis
getAxes
xTitle
xAxisFormat
xAxisAngle
xType
xGrid
yTitle
yAxisFormat
yType
yGrid
chartType
-- legend
local
legend
if
legendTitle
and
tonumber
legendTitle
~=
then
legend
getLegend
legendTitle
chartType
outerRadius
end
-- construct final output object
local
output
version
width
graphwidth
height
graphheight
data
data
},
scales
scales
axes
xAxis
yAxis
},
marks
marks
legends
legend
if
vannoData
then
table.insert
output
data
vannoData
end
if
hannoData
then
table.insert
output
data
hannoData
end
if
stats
then
table.insert
output
data
stats
end
local
flags
if
formatJson
then
flags
mw
text
JSON_PRETTY
end
return
mw
text
jsonEncode
output
flags
end
function
mapWrapper
frame
return
map
frame
getParent
())
end
function
chartWrapper
frame
return
chart
frame
getParent
())
end
function
chartDebuger
frame
return
\n\n
chart JSON
\n
..
chart
frame
..
\n\n
..
debuglog
end
-- Given an HTML-encoded title as first argument, e.g. one produced with {{ARTICLEPAGENAME}},
-- convert it into a properly URL path-encoded string
-- This function is critical for any graph that uses path-based APIs, e.g. PageViews graph
function
encodeTitleForPath
frame
return
mw
uri
encode
mw
text
decode
mw
text
trim
frame
args
])),
'PATH'
end
return
Abgerufen von „
Kategorie
Wikipedia:Lua/Modul/Global via WikiData/Mutter
Modul
Graph
Abschnitt hinzufügen