Jump to content
Wikipedia The Free Encyclopedia

Module:Graph

From Wikipedia, the free encyclopedia
Module documentation[view] [edit] [history] [purge]
This module is being discussed in accordance with Wikipedia's deletion policy. Help reach a consensus at its entry.
%5B%5BWikipedia%3ATemplates+for+discussion%2FLog%2F2025+December+1%23Module%3AGraph%5D%5D
Warning This Lua module is used on approximately 3,300 pages and changes may be widely noticed. Test changes in the module's /sandbox or /testcases subpages, or in your own module sandbox. Consider discussing changes on the talk page before implementing them.
This module is rated as deprecated and defunct. It is recommended editors use Chart extension .
Page template-protected This module is currently protected from editing.
See the protection policy and protection log for more details. Please discuss any changes on the talk page; you may submit an edit request to ask an administrator to make an edit if it is uncontroversial or supported by consensus. You may also request that this page be unprotected.
Converting to the Chart extension: To convert the defunct {{Graph}}-based diagrams to the newer Chart Extension format, you can use the simple script featured on MediaWiki at Commons: graphDataImport.js.
Related pages

Module with helper functions for the Graph extension to display graphs and maps. From de:Modul:Graph.

Functions for templates

map

Creates a JSON object for <graph> to display a political map with colored highlights. In the article namespace the template {{Graph:Map }} should be used instead. See its page for use cases.

Maps can be found at Special:Prefixindex/Template:Graph:Map/Inner/ (for example Worldmap2c-json with country borders) and new maps should also be saved under Module:Graph/.

Parameters:

  • basemap: sets the base map. The map definitions must follow the TopoJSON format and if saved in Wikipedia are available for this module. Maps in the default directory Special:Prefixindex/Template:Graph:Map/Inner/ like Worldmap2c-json should only be referenced by their name while omitting the Module:Graph/ prefix to allow better portability. The parameter also accepts URLs, e.g. maps from other Wikipedia versions (the link should follow the scheme of //en.wikipedia.org/w/index.php?title=mapname&action=raw, i.e. protocol-relative without leading http/s and a trailing action=raw to fetch the raw content only). URLs to maps on external sites should be avoided for the sake of link stability, performance, security, and she be assumed to be blocked by the software or browser anyway.
  • scale: the scaling factor of the map (default: 100)
  • projection: the map projection to use. Supported values are listed at https://github.com/d3/d3-geo-projection. The default value is equirectangular for an equirectangular projection.
  • center: map center (corresponds in the map data to both comma-separated values of the scale field)
  • feature: which geographic objects should be displayed (corresponds in the map data to the name of the field under the objects field). The default is value countries.
  • ids of geographic entities: The actual parameter names depend on the base map and the selected feature. For example, for the above mentioned world map the ids are ISO country codes. The values can be either colors or numbers in case the geographic entities should be associated with numeric data: DE=lightblue marks Germany in light blue color, and DE=80.6 assigns Germany the value 80.6 (population in millions). In the latter case, the actual color depends on the following parameters.
  • colorScale: the color palette to use for the color scale. The palette must be provided as a comma-separated list of color values. The color values must be given either as #rgb/#rrggbb or by a CSS color name. Instead of a list, the built-in color palettes category10 and category20 can also be used.
  • scaleType: supported values are linear for a linear mapping between the data values and the color scale, log for a log mapping, pow for a power mapping (the exponent can be provided as pow 0.5), sqrt for a square-root mapping, and quantize for a quantized scale, i.e. the data is grouped in as many classes as the color palette has colors.
  • domainMin: lower boundary of the data values, i.e. smaller data values are mapped to the lower boundary
  • domainMax: upper boundary of the data values, i.e. larger data values are mapped to the upper boundary
  • legend: show color legend (does not work with quantize)
  • defaultValue: default value for unused geographic entities. In case the id values are colors the default value is silver, in case of numbers it is 0.
  • formatjson: format JSON object for better legibility
  • title: The title of the graph, used by User:GraphBot when converting.
  • name: The name of the graph, required by User:GraphBot to convert the graph.

chart

Creates a JSON object for <graph> to display charts. In the article namespace the template Template:Graph:Chart should be used instead. See its page for use cases.

Parameters:

  • width: width of the chart
  • height: height of the chart
  • type: type of the chart: line for line charts, area for area charts, and rect for (column) bar charts, and pie for pie charts. Multiple series can stacked using the stacked prefix, e.g. stackedarea.
  • interpolate: interpolation method for line and area charts. It is recommended to use monotone for a monotone cubic interpolation – further supported values are listed at https://github.com/nyurik/vega/wiki/Marks#line.
  • colors: color palette of the chart as a comma-separated list of colors. The color values must be given either as #rgb/#rrggbb/#aarrggbb or by a CSS color name. For #aarrggbb the aa component denotes the alpha channel, i.e. FF=100% opacity, 80=50% opacity/transparency, etc. (The default color palette if n <= 10 is Category10:                                         else is Category20:                                                                                ). See Template:ChartColors for details.
  • xAxisTitle and yAxisTitle: captions of the x and y axes
  • xAxisMin, xAxisMax, yAxisMin, and yAxisMax: minimum and maximum values of the x and y axes (not yet supported for bar charts). These parameters can be used to invert the scale of a numeric axis by setting the lowest value to the Max and highest value to the Min.
  • xAxisFormat and yAxisFormat: changes the formatting of the axis labels. Supported values are listed at https://github.com/d3/d3-3.x-api-reference/blob/master/Formatting.md#numbers for numbers. For example, the format % can be used to output percentages. For date/time specification of supported values is https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Formatting.md , e.g. xAxisFormat=%d-%m-%Y for result 13-01-1977.
  • xAxisAngle: rotates the x axis labels by the specified angle. Recommended values are: -45, +45, -90, +90
  • xType and yType: data types of the values, e.g. integer for integers, number for real numbers, date for dates (e.g. YYYY-MM-DD), and string for ordinal values (use string to prevent axis values from being repeated when there are only a few values). Remarks: Date type doesn't work for bar graphs. For date data input please use ISO date format (e.g. YYYY-MM-DD) acc. to date and time formats used in HTML. Other date formats may work but not in all browsers. Date is unfortunately displayed only in en-US format for all Wikipedia languages. Workaround is to use xAxisFormat and yAxisFormat with numerical dates format.
  • xScaleType and yScaleType: scale types of the x and y axes, e.g. linear for linear scale (default), log for logarithmic scale and sqrt for square root scale.
    A logarithmic chart allows only positive values to be plotted. A square root scale chart cannot show negative values.
  • x: the x-values as a comma-separated list, for dates and time see remark in xType and yType
  • y or y1, y2, ...: the y-values for one or several data series, respectively. For pie charts y2 denotes the radius of the corresponding sectors. For dates and time see remark in xType and yType
  • legend: show legend (only works in case of multiple data series)
  • y1Title, y2Title, ...: defines the label of the respective data series in the legend
  • linewidth: line width for line charts or distance between the pie segments for pie charts. Setting to 0 with type=line creates a scatter plot.
  • linewidths: different line widths may be defined for each series of data with csv, if set to 0 with "showSymbols" results with points graph, eg.: linewidths=1, 0, 5, 0.2
  • showSymbols: show symbol on data point for line graphs, if a number is provided, the symbol size (default 2.5) may be defined for each data series, eg.: showSymbols=1, 2, 3, 4
  • symbolsShape: custom shape for symbol: circle, x, square, cross, diamond, triangle_up, triangle_down, triangle_right, triangle_left. May be defined for each series of data with csv, eg.: symbolsShape= circle, cross, square
  • symbolsNoFill: if true symbol will be without fill (only stroke),
  • symbolsStroke: if "x" symbol is used or option "symbolsNoFill" symbol stroke width, default 2.5
  • showValues: Additionally, output the y values as text. (Currently, only (non-stacked) bar and pie charts are supported.) The output can be configured used the following parameters provided as name1:value1, name2:value2 (e.g. |showValues=fontcolor:blue,angle:0).
  • innerRadius: For pie charts: defines the inner radius to create a doughnut chart.
  • xGrid and yGrid: display grid lines on the x and y axes.
  • Annotations
    • vAnnotatonsLine and hAnnotatonsLine: display vertical or horizontal annotation lines on specific values e.g. hAnnotatonsLine=4, 5, 6
    • vAnnotatonsLabel and hAnnotatonsLabel: display vertical or horizontal annotation labels for lines e.g. hAnnotatonsLabel = label1, label2, label3
  • formatjson: format JSON object for better legibility
  • title: The title of the graph, used by User:GraphBot when converting.
  • name: The name of the graph, required by User:GraphBot to convert the graph.

Template wrappers

The functions mapWrapper and chartWrapper are wrappers to pass all parameters of the calling template to the respective map and chart functions.

Note: In the editor preview the graph extension creates a canvas element with vector graphics. However, when saving the page a PNG raster graphics is generated instead. {{#invoke:Graph|function_wrapper_name}}

The above documentation is transcluded from Module:Graph/doc. (edit | history)
Editors can experiment in this module's sandbox (edit | diff) and testcases (create) pages.
Subpages of this module.

 -- 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 [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.

 localp={}

 --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"

 localbaseMapDirectory="Module:Graph/"
 localpersistentGrey="#54595d"

 localshapes={}
 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"
 }


 localfunctionnumericArray(csv)
 ifnotcsvthenreturnend

 locallist=mw.text.split(csv,"%s*,%s*")
 localresult={}
 localisInteger=true
 fori=1,#listdo
 iflist[i]==""then
 result[i]=nil
 else
 result[i]=tonumber(list[i])
 ifnotresult[i]thenreturnend
 ifisIntegerthen
 localint,frac=math.modf(result[i])
 isInteger=frac==0.0
 end
 end
 end

 returnresult,isInteger
 end

 localfunctionstringArray(text)
 ifnottextthenreturnend

 locallist=mw.text.split(mw.ustring.gsub(tostring(text),"\\,","<COMMA>"),",",true)
 fori=1,#listdo
 list[i]=mw.ustring.gsub(mw.text.trim(list[i]),"<COMMA>",",")
 end
 returnlist
 end

 localfunctionisTable(t)returntype(t)=="table"end

 localfunctioncopy(x)
 iftype(x)=="table"then
 localresult={}
 forkey,valueinpairs(x)doresult[key]=copy(value)end
 returnresult
 else
 returnx
 end
 end

 functionp.map(frame)
 -- map path data for geographic objects
 localbasemap=frame.args.basemapor"Template:Graph:Map/Inner/Worldmap2c-json"-- WorldMap name and/or location may vary from wiki to wiki
 -- scaling factor
 localscale=tonumber(frame.args.scale)or100
 -- map projection, see https://github.com/mbostock/d3/wiki/Geo-Projections
 localprojection=frame.args.projectionor"equirectangular"
 -- defaultValue for geographic objects without data
 localdefaultValue=frame.args.defaultValueorframe.args.defaultvalue
 localscaleType=frame.args.scaleTypeorframe.args.scaletypeor"linear"
 -- minimaler Wertebereich (nur für numerische Daten)
 localdomainMin=tonumber(frame.args.domainMinorframe.args.domainmin)
 -- maximaler Wertebereich (nur für numerische Daten)
 localdomainMax=tonumber(frame.args.domainMaxorframe.args.domainmax)
 -- Farbwerte der Farbskala (nur für numerische Daten)
 localcolorScale=frame.args.colorScaleorframe.args.colorscaleor"category10"
 -- show legend
 locallegend=frame.args.legend
 -- the map feature to display
 localfeature=frame.args.featureor"countries"
 -- map center
 localcenter=numericArray(frame.args.center)
 -- format JSON output
 localformatJson=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
 localvalues={}
 localisNumbers=nil
 forname,valueinpairs(frame.args)do
 ifmw.ustring.find(name,"^[^%l]+$")andvalueandvalue~=""then
 ifisNumbers==nilthenisNumbers=tonumber(value)end
 localdata={id=name,v=value}
 ifisNumbersthendata.v=tonumber(data.v)end
 table.insert(values,data)
 end
 end
 ifnotdefaultValuethen
 ifisNumbersthendefaultValue=0elsedefaultValue="silver"end
 end

 -- create highlight scale
 localscales
 ifisNumbersthen
 ifcolorScalethencolorScale=string.lower(colorScale)end
 ifcolorScale=="category10"orcolorScale=="category20"thenelsecolorScale=stringArray(colorScale)end
 scales=
 {
 {
 name="color",
 type=scaleType,
 domain={data="highlights",field="v"},
 range=colorScale,
 nice=true,
 zero=false
 }
 }
 ifdomainMinthenscales[1].domainMin=domainMinend
 ifdomainMaxthenscales[1].domainMax=domainMaxend

 localexponent=string.match(scaleType,"pow%s+(%d+%.?%d+)")-- check for exponent
 ifexponentthen
 scales[1].type="pow"
 scales[1].exponent=exponent
 end
 end

 -- create legend
 iflegendthen
 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
 localbasemapUrl
 if(string.sub(basemap,1,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.
 ifnotstring.find(basemap,":")thenbasemap=baseMapDirectory..basemapend
 basemapUrl="wikiraw:///"..mw.uri.encode(mw.title.new(basemap).prefixedText,"PATH")
 end

 localoutput=
 {
 version=2,
 width=1,-- generic value as output size depends solely on map size and scaling factor
 height=1,-- 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={0,0},
 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={v=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[1].properties.update.fill.scale="color"
 end

 localflags
 ifformatJsonthenflags=mw.text.JSON_PRETTYend
 returnmw.text.jsonEncode(output,flags)
 end

 localfunctiondeserializeXData(serializedX,xType,xMin,xMax)
 localx

 ifnotxTypeorxType=="integer"orxType=="number"then
 localisInteger
 x,isInteger=numericArray(serializedX)
 ifxthen
 xMin=tonumber(xMin)
 xMax=tonumber(xMax)
 ifnotxTypethen
 ifisIntegerthenxType="integer"elsexType="number"end
 end
 else
 ifxTypethenerror("Numbers expected for parameter 'x'")end
 end
 end
 ifnotxthen
 x=stringArray(serializedX)
 ifnotxTypethenxType="string"end
 end
 returnx,xType,xMin,xMax
 end

 localfunctiondeserializeYData(serializedYs,yType,yMin,yMax)
 localy={}
 localareAllInteger=true

 foryNum,valueinpairs(serializedYs)do
 localyValues
 ifnotyTypeoryType=="integer"oryType=="number"then
 localisInteger
 yValues,isInteger=numericArray(value)
 ifyValuesthen
 areAllInteger=areAllIntegerandisInteger
 else
 ifyTypethen
 error("Numbers expected for parameter '"..name.."'")
 else
 returndeserializeYData(serializedYs,"string",yMin,yMax)
 end
 end
 end
 ifnotyValuesthenyValues=stringArray(value)end

 y[yNum]=yValues
 end
 ifnotyTypethen
 ifareAllIntegerthenyType="integer"elseyType="number"end
 end
 ifyType=="integer"oryType=="number"then
 yMin=tonumber(yMin)
 yMax=tonumber(yMax)
 end

 returny,yType,yMin,yMax
 end

 localfunctionconvertXYToManySeries(x,y,xType,yType,seriesTitles)
 localdata=
 {
 name="chart",
 format=
 {
 type="json",
 parse={x=xType,y=yType}
 },
 values={}
 }
 fori=1,#ydo
 localyLen=table.maxn(y[i])
 forj=1,#xdo
 ifj<=yLenandy[i][j]thentable.insert(data.values,{series=seriesTitles[i],x=x[j],y=y[i][j]})end
 end
 end
 returndata
 end

 localfunctionconvertXYToSingleSeries(x,y,xType,yType,yNames)
 localdata={name="chart",format={type="json",parse={x=xType}},values={}}

 forj=1,#ydodata.format.parse[yNames[j]]=yTypeend

 fori=1,#xdo
 localitem={x=x[i]}
 forj=1,#ydoitem[yNames[j]]=y[j][i]end

 table.insert(data.values,item)
 end
 returndata
 end

 localfunctiongetXScale(chartType,stacked,xMin,xMax,xType,xScaleType)
 ifchartType=="pie"thenreturnend

 localxscale=
 {
 name="x",
 range="width",
 zero=false,-- do not include zero value
 domain={data="chart",field="x"}
 }
 ifxScaleTypethenxscale.type=xScaleTypeelsexscale.type="linear"end
 ifxMinthenxscale.domainMin=xMinend
 ifxMaxthenxscale.domainMax=xMaxend
 ifxMinorxMaxthen
 xscale.clamp=true
 xscale.nice=false
 end
 ifchartType=="rect"then
 xscale.type="ordinal"
 ifnotstackedthenxscale.padding=0.2end-- pad each bar group
 else
 ifxType=="date"then
 xscale.type="time"
 elseifxType=="string"then
 xscale.type="ordinal"
 xscale.points=true
 end
 end
 ifxTypeandxType~="date"andxScaleType~="log"thenxscale.nice=trueend-- force round numbers for x scale, but "log" and "date" scale outputs a wrong "nice" scale
 returnxscale
 end

 localfunctiongetYScale(chartType,stacked,yMin,yMax,yType,yScaleType)
 ifchartType=="pie"thenreturnend

 localyscale=
 {
 name="y",
 --type = yScaleType or "linear",
 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
 }
 ifyScaleTypethenyscale.type=yScaleTypeelseyscale.type="linear"end
 ifyMinthenyscale.domainMin=yMinend
 ifyMaxthenyscale.domainMax=yMaxend
 ifyMinoryMaxthenyscale.clamp=trueend
 ifyType=="date"thenyscale.type="time"
 elseifyType=="string"thenyscale.type="ordinal"end
 ifstackedthen
 yscale.domain={data="stats",field="sum_y"}
 else
 yscale.domain={data="chart",field="y"}
 end

 returnyscale
 end

 localfunctiongetColorScale(colors,chartType,xCount,yCount)
 ifnotcolorsthen
 if(chartType=="pie"andxCount>10)oryCount>10thencolors="category20"elsecolors="category10"end
 end

 localcolorScale=
 {
 name="color",
 type="ordinal",
 range=colors,
 domain={data="chart",field="series"}
 }
 ifchartType=="pie"thencolorScale.domain.field="x"end
 returncolorScale
 end

 localfunctiongetAlphaColorScale(colors,y)
 localalphaScale
 -- if there is at least one color in the format "#aarrggbb", create a transparency (alpha) scale
 ifisTable(colors)then
 localalphas={}
 localhasAlpha=false
 fori=1,#colorsdo
 locala,rgb=string.match(colors[i],"#(%x%x)(%x%x%x%x%x%x)")
 ifathen
 hasAlpha=true
 alphas[i]=tostring(tonumber(a,16)/255.0)
 colors[i]="#"..rgb
 else
 alphas[i]="1"
 end
 end
 fori=#colors+1,#ydoalphas[i]="1"end
 ifhasAlphathenalphaScale={name="transparency",type="ordinal",range=alphas}end
 end
 returnalphaScale
 end

 localfunctiongetLineScale(linewidths,chartType)
 locallineScale={}

 lineScale=
 {
 name="line",
 type="ordinal",
 range=linewidths,
 domain={data="chart",field="series"}
 }

 returnlineScale
 end

 localfunctiongetSymSizeScale(symSize)
 localSymSizeScale={}
 SymSizeScale=
 {
 name="symSize",
 type="ordinal",
 range=symSize,
 domain={data="chart",field="series"}
 }

 returnSymSizeScale
 end

 localfunctiongetSymShapeScale(symShape)
 localSymShapeScale={}
 SymShapeScale=
 {
 name="symShape",
 type="ordinal",
 range=symShape,
 domain={data="chart",field="series"}
 }

 returnSymShapeScale
 end

 localfunctiongetValueScale(fieldName,min,max,type)
 localvalueScale=
 {
 name=fieldName,
 type=typeor"linear",
 domain={data="chart",field=fieldName},
 range={min,max}
 }
 returnvalueScale
 end

 localfunctionaddInteractionToChartVisualisation(plotMarks,colorField,dataField)
 -- initial setup
 ifnotplotMarks.properties.enterthenplotMarks.properties.enter={}end
 plotMarks.properties.enter[colorField]={scale="color",field=dataField}

 -- action when cursor is over plot mark: highlight
 ifnotplotMarks.properties.hoverthenplotMarks.properties.hover={}end
 plotMarks.properties.hover[colorField]={value="red"}

 -- action when cursor leaves plot mark: reset to initial setup
 ifnotplotMarks.properties.updatethenplotMarks.properties.update={}end
 plotMarks.properties.update[colorField]={scale="color",field=dataField}
 end

 localfunctiongetPieChartVisualisation(yCount,innerRadius,outerRadius,linewidth,radiusScale)
 localchartvis=
 {
 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=linewidthor1}
 }
 }
 }

 ifradiusScalethen
 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")

 returnchartvis
 end

 localfunctiongetChartVisualisation(chartType,stacked,colorField,yCount,innerRadius,outerRadius,linewidth,alphaScale,radiusScale,lineScale,interpolate)
 ifchartType=="pie"thenreturngetPieChartVisualisation(yCount,innerRadius,outerRadius,linewidth,radiusScale)end

 localchartvis=
 {
 type=chartType,
 properties=
 {
 -- chart creation event handler
 enter=
 {
 x={scale="x",field="x"},
 y={scale="y",field="y"}
 }
 }
 }
 addInteractionToChartVisualisation(chartvis,colorField,"series")
 ifcolorField=="stroke"then
 chartvis.properties.enter.strokeWidth={value=linewidthor2.5}
 iftype(lineScale)=="table"then
 chartvis.properties.enter.strokeWidth.value=nil
 chartvis.properties.enter.strokeWidth=
 {
 scale="line",
 field="series"
 }
 end
 end

 ifinterpolatethenchartvis.properties.enter.interpolate={value=interpolate}end

 ifalphaScalethenchartvis.properties.update[colorField.."Opacity"]={scale="transparency"}end
 -- for bars and area charts set the lower bound of their areas
 ifchartType=="rect"orchartType=="area"then
 ifstackedthen
 -- 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 ...
 ifchartType=="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
 ifnotstackedandyCount>1then
 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
 ifstackedthenchartvis.properties.enter.y.field="layout_start"end

 -- if there are multiple series group these together
 ifyCount==1then
 chartvis.from={data="chart"}
 else
 -- if there are multiple series, connect colors to series
 chartvis.properties.update[colorField].field="series"
 ifalphaScalethenchartvis.properties.update[colorField.."Opacity"].field="series"end

 -- if there are multiple series, connect linewidths to series
 ifchartype=="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
 ifstackedthen
 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
 ifchartType=="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
 localgroupScale=
 {
 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

 returnchartvis
 end

 localfunctiongetTextMarks(chartvis,chartType,outerRadius,scales,radiusScale,yType,showValues)
 localproperties
 ifchartType=="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)or11}
 }
 ifproperties.y.offset>=0then
 properties.align.value="right"
 properties.fill.value=showValues.fontcoloror"white"
 else
 properties.align.value="left"
 properties.fill.value=showValues.fontcolororpersistentGrey
 end
 elseifchartType=="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.fontcolororpersistentGrey},
 baseline={},
 angle={},
 fontSize={value=tonumber(showValues.fontsize)ormath.ceil(outerRadius/10)}
 }
 if(showValues.angleor"midangle")=="midangle"then
 properties.align={value="center"}
 properties.angle={field="layout_mid",mult=180.0/math.pi}

 ifproperties.radius.offset>=0then
 properties.baseline.value="bottom"
 else
 ifnotshowValues.fontcolorthenproperties.fill.value="white"end
 properties.baseline.value="top"
 end
 elseiftonumber(showValues.angle)then
 -- qunatize scale for aligning text left on right half-circle and right on left half-circle
 localalignScale={name="align",type="quantize",domainMin=0.0,domainMax=math.pi*2,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"
 ifnottonumber(showValues.offset)thenproperties.radius.offset=4end
 end

 ifradiusScalethen
 properties.radius.scale=radiusScale.name
 properties.radius.field=radiusScale.domain.field
 else
 properties.radius.value=outerRadius
 end
 end

 ifpropertiesthen
 ifshowValues.formatthen
 localtemplate="datum.y"
 ifyType=="integer"oryType=="number"thentemplate=template.."|number:'"..showValues.format.."'"
 elseifyType=="date"thentemplate=template.."|time:"..showValues.format.."'"
 end
 properties.text={template="{{"..template.."}}"}
 else
 properties.text={field="y"}
 end

 localtextmarks=
 {
 type="text",
 properties=
 {
 enter=properties
 }
 }
 ifchartvis.fromthentextmarks.from=copy(chartvis.from)end

 returntextmarks
 end
 end

 localfunctiongetSymbolMarks(chartvis,symSize,symShape,symStroke,noFill,alphaScale)

 localsymbolmarks
 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"},
 }
 }
 }
 iftype(symShape)=="string"then
 symbolmarks.properties.enter.shape={value=symShape}
 end
 iftype(symShape)=="table"then
 symbolmarks.properties.enter.shape={scale="symShape",field="series"}
 end
 iftype(symSize)=="number"then
 symbolmarks.properties.enter.size={value=symSize}
 end
 iftype(symSize)=="table"then
 symbolmarks.properties.enter.size={scale="symSize",field="series"}
 end
 ifnoFillthen
 symbolmarks.properties.enter.fill=nil
 end
 ifalphaScalethen
 symbolmarks.properties.enter.fillOpacity=
 {scale="transparency",field="series"}
 symbolmarks.properties.enter.strokeOpacity=
 {scale="transparency",field="series"}
 end
 ifchartvis.fromthensymbolmarks.from=copy(chartvis.from)end

 returnsymbolmarks
 end

 localfunctiongetAnnoMarks(chartvis,stroke,fill,opacity)

 localvannolines,hannolines,vannoLabels,vannoLabels
 vannolines=
 {
 type="rule",
 from={data="v_anno"},
 properties=
 {
 update=
 {
 x={scale="x",field="x"},
 y={value=0},
 y2={field={group="height"}},
 strokeWidth={value=stroke},
 stroke={value=persistentGrey},
 opacity={value=opacity}
 }
 }
 }
 vannolabels=
 {
 type="text",
 from={data="v_anno"},
 properties=
 {
 update=
 {
 x={scale="x",field="x",offset=3},
 y={field={group="height"},offset=-3},
 text={field="label"},
 baseline={value="top"},
 angle={value=-90},
 fill={value=persistentGrey},
 opacity={value=opacity}
 }
 }
 }
 hannolines=
 {
 type="rule",
 from={data="h_anno"},
 properties=
 {
 update=
 {
 y={scale="y",field="y"},
 x={value=0},
 x2={field={group="width"}},
 strokeWidth={value=stroke},
 stroke={value=persistentGrey},
 opacity={value=opacity}
 }
 }
 }
 hannolabels=
 {
 type="text",
 from={data="h_anno"},
 properties=
 {
 update=
 {
 y={scale="y",field="y",offset=3},
 x={value=0,offset=3},
 text={field="label"},
 baseline={value="top"},
 angle={value=0},
 fill={value=persistentGrey},
 opacity={value=opacity}
 }
 }
 }
 returnvannolines,vannolabels,hannolines,hannolabels
 end

 localfunctiongetAxes(xTitle,xAxisFormat,xAxisAngle,xType,xGrid,yTitle,yAxisFormat,yType,yGrid,chartType)
 localxAxis,yAxis
 ifchartType~="pie"then
 ifxType=="integer"andnotxAxisFormatthenxAxisFormat="d"end
 xAxis=
 {
 type="x",
 scale="x",
 title=xTitle,
 format=xAxisFormat,
 grid=xGrid
 }
 ifxAxisAnglethen
 localxAxisAlign
 ifxAxisAngle<0thenxAxisAlign="right"elsexAxisAlign="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=2}
 },
 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=2}
 },
 grid=
 {
 stroke={value=persistentGrey}
 }
 }
 end

 ifyType=="integer"andnotyAxisFormatthenyAxisFormat="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=2}
 },
 grid=
 {
 stroke={value=persistentGrey}
 }
 }

 end

 returnxAxis,yAxis
 end

 localfunctiongetLegend(legendTitle,chartType,outerRadius)
 locallegend=
 {
 fill="color",
 stroke="color",
 title=legendTitle,
 }
 legend.properties={
 title={
 fill={value=persistentGrey},
 },
 labels={
 fill={value=persistentGrey},
 },
 }
 ifchartType=="pie"then
 legend.properties={
 -- move legend from center position to top
 legend={
 y={value=-outerRadius},
 },
 title={
 fill={value=persistentGrey}
 },
 labels={
 fill={value=persistentGrey},
 },
 }
 end
 returnlegend
 end

 functionp.chart(frame)
 -- chart width and height
 localgraphwidth=tonumber(frame.args.width)or200
 localgraphheight=tonumber(frame.args.height)or200
 -- chart type
 localchartType=frame.args.typeor"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
 localinterpolate=frame.args.interpolate
 -- mark colors (if no colors are given, the default 10 color palette is used)
 localcolorString=frame.args.colors
 ifcolorStringthencolorString=string.lower(colorString)end
 localcolors=stringArray(colorString)
 -- for line charts, the thickness of the line; for pie charts the gap between each slice
 locallinewidth=tonumber(frame.args.linewidth)
 locallinewidthsString=frame.args.linewidths
 locallinewidths
 iflinewidthsStringandlinewidthsString~=""thenlinewidths=numericArray(linewidthsString)orfalseend
 -- x and y axis caption
 localxTitle=frame.args.xAxisTitleorframe.args.xaxistitle
 localyTitle=frame.args.yAxisTitleorframe.args.yaxistitle
 -- x and y value types
 localxType=frame.args.xTypeorframe.args.xtype
 localyType=frame.args.yTypeorframe.args.ytype
 -- override x and y axis minimum and maximum
 localxMin=frame.args.xAxisMinorframe.args.xaxismin
 localxMax=frame.args.xAxisMaxorframe.args.xaxismax
 localyMin=frame.args.yAxisMinorframe.args.yaxismin
 localyMax=frame.args.yAxisMaxorframe.args.yaxismax
 -- override x and y axis label formatting
 localxAxisFormat=frame.args.xAxisFormatorframe.args.xaxisformat
 localyAxisFormat=frame.args.yAxisFormatorframe.args.yaxisformat
 localxAxisAngle=tonumber(frame.args.xAxisAngle)ortonumber(frame.args.xaxisangle)
 -- x and y scale types
 localxScaleType=frame.args.xScaleTypeorframe.args.xscaletype
 localyScaleType=frame.args.yScaleTypeorframe.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
 localxGrid=frame.args.xGridorframe.args.xgridorfalse
 localyGrid=frame.args.yGridorframe.args.ygridorfalse
 -- for line chart, show a symbol at each data point
 localshowSymbols=frame.args.showSymbolsorframe.args.showsymbols
 localsymbolsShape=frame.args.symbolsShapeorframe.args.symbolsshape
 localsymbolsNoFill=frame.args.symbolsNoFillorframe.args.symbolsnofill
 localsymbolsStroke=tonumber(frame.args.symbolsStrokeorframe.args.symbolsstroke)
 -- show legend with given title
 locallegendTitle=frame.args.legend
 -- show values as text
 localshowValues=frame.args.showValuesorframe.args.showvalues
 -- show v- and h-line annotations
 localv_annoLineString=frame.args.vAnnotatonsLineorframe.args.vannotatonsline
 localh_annoLineString=frame.args.hAnnotatonsLineorframe.args.hannotatonsline
 localv_annoLabelString=frame.args.vAnnotatonsLabelorframe.args.vannotatonslabel
 localh_annoLabelString=frame.args.hAnnotatonsLabelorframe.args.hannotatonslabel





 -- decode annotations cvs
 localv_annoLine,v_annoLabel,h_annoLine,h_annoLabel
 ifv_annoLineStringandv_annoLineString~=""then

 ifxType=="number"orxType=="integer"then
 v_annoLine=numericArray(v_annoLineString)

 else
 v_annoLine=stringArray(v_annoLineString)

 end
 v_annoLabel=stringArray(v_annoLabelString)
 end
 ifh_annoLineStringandh_annoLineString~=""then

 ifyType=="number"oryType=="integer"then
 h_annoLine=numericArray(h_annoLineString)

 else
 h_annoLine=stringArray(h_annoLineString)

 end
 h_annoLabel=stringArray(h_annoLabelString)
 end





 -- pie chart radiuses
 localinnerRadius=tonumber(frame.args.innerRadius)ortonumber(frame.args.innerradius)or0
 localouterRadius=math.min(graphwidth,graphheight)
 -- format JSON output
 localformatJson=frame.args.formatjson

 -- get x values
 localx
 x,xType,xMin,xMax=deserializeXData(frame.args.x,xType,xMin,xMax)

 -- get y values (series)
 localyValues={}
 localseriesTitles={}
 forname,valueinpairs(frame.args)do
 localyNum
 ifname=="y"thenyNum=1elseyNum=tonumber(string.match(name,"^y(%d+)$"))end
 ifyNumthen
 yValues[yNum]=value
 -- name the series: default is "y<number>". Can be overwritten using the "y<number>Title" parameters.
 seriesTitles[yNum]=frame.args["y"..yNum.."Title"]orframe.args["y"..yNum.."title"]orname
 end
 end
 localy
 y,yType,yMin,yMax=deserializeYData(yValues,yType,yMin,yMax)

 -- create data tuples, consisting of series index, x value, y value
 localdata
 ifchartType=="pie"then
 -- for pie charts the second second series is merged into the first series as radius values
 data=convertXYToSingleSeries(x,y,xType,yType,{"y","r"})
 else
 data=convertXYToManySeries(x,y,xType,yType,seriesTitles)
 end

 -- configure stacked charts
 localstacked=false
 localstats
 ifstring.sub(chartType,1,7)=="stacked"then
 chartType=string.sub(chartType,8)
 if#y>1then-- 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={y="sum"}
 }
 }
 }
 end
 end

 -- add annotations to data
 localvannoData,hannoData

 ifv_annoLinethen
 vannoData={name="v_anno",format={type="json",parse={x=xType}},values={}}
 fori=1,#v_annoLinedo
 localitem={x=v_annoLine[i],label=v_annoLabel[i]}
 table.insert(vannoData.values,item)
 end
 end
 ifh_annoLinethen
 hannoData={name="h_anno",format={type="json",parse={y=yType}},values={}}
 fori=1,#h_annoLinedo
 localitem={y=h_annoLine[i],label=h_annoLabel[i]}
 table.insert(hannoData.values,item)
 end
 end


 -- create scales
 localscales={}

 localxscale=getXScale(chartType,stacked,xMin,xMax,xType,xScaleType)
 table.insert(scales,xscale)
 localyscale=getYScale(chartType,stacked,yMin,yMax,yType,yScaleType)
 table.insert(scales,yscale)

 localcolorScale=getColorScale(colors,chartType,#x,#y)
 table.insert(scales,colorScale)

 localalphaScale=getAlphaColorScale(colors,y)
 table.insert(scales,alphaScale)

 locallineScale
 if(linewidths)and(chartType=="line")then
 lineScale=getLineScale(linewidths,chartType)
 table.insert(scales,lineScale)
 end

 localradiusScale
 ifchartType=="pie"and#y>1then
 radiusScale=getValueScale("r",0,outerRadius)
 table.insert(scales,radiusScale)
 end

 -- decide if lines (strokes) or areas (fills) should be drawn
 localcolorField
 ifchartType=="line"thencolorField="stroke"elsecolorField="fill"end



 -- create chart markings
 localchartvis=getChartVisualisation(chartType,stacked,colorField,#y,innerRadius,outerRadius,linewidth,alphaScale,radiusScale,lineScale,interpolate)
 localmarks={chartvis}

 -- text marks
 ifshowValuesthen
 iftype(showValues)=="string"then-- deserialize as table
 localkeyValues=mw.text.split(showValues,"%s*,%s*")
 showValues={}
 for_,kvinipairs(keyValues)do
 localkey,value=mw.ustring.match(kv,"^%s*(.-)%s*:%s*(.-)%s*$")
 ifkeythenshowValues[key]=valueend
 end
 end

 localchartmarks=chartvis
 ifchartmarks.marksthenchartmarks=chartmarks.marks[1]end
 localtextmarks=getTextMarks(chartmarks,chartType,outerRadius,scales,radiusScale,yType,showValues)
 ifchartmarks~=chartvisthen
 table.insert(chartvis.marks,textmarks)
 else
 table.insert(marks,textmarks)
 end
 end

 -- grids
 ifxGridthen
 ifxGrid=="0"thenxGrid=false
 elseifxGrid==0thenxGrid=false
 elseifxGrid=="false"thenxGrid=false
 elseifxGrid=="n"thenxGrid=false
 elsexGrid=true
 end
 end
 ifyGridthen
 ifyGrid=="0"thenyGrid=false
 elseifyGrid==0thenyGrid=false
 elseifyGrid=="false"thenyGrid=false
 elseifyGrid=="n"thenyGrid=false
 elseyGrid=true
 end
 end

 -- symbol marks
 ifshowSymbolsandchartType~="rect"then
 localchartmarks=chartvis
 ifchartmarks.marksthenchartmarks=chartmarks.marks[1]end

 iftype(showSymbols)=="string"then
 ifshowSymbols==""thenshowSymbols=true
 elseshowSymbols=numericArray(showSymbols)
 end
 else
 showSymbols=tonumber(showSymbols)
 end

 -- custom size
 localsymSize
 iftype(showSymbols)=="number"then
 symSize=tonumber(showSymbols*showSymbols*8.5)
 elseiftype(showSymbols)=="table"then
 symSize={}
 fork,vinpairs(showSymbols)do
 symSize[k]=v*v*8.5-- "size" acc to Vega syntax is area of symbol
 end
 else
 symSize=50
 end
 -- symSizeScale 
 localsymSizeScale={}
 iftype(symSize)=="table"then
 symSizeScale=getSymSizeScale(symSize)
 table.insert(scales,symSizeScale)
 end


 -- custom shape
 ifstringArray(symbolsShape)and#stringArray(symbolsShape)>1thensymbolsShape=stringArray(symbolsShape)end

 localsymShape=" "

 iftype(symbolsShape)=="string"andshapes[symbolsShape]then
 symShape=shapes[symbolsShape]
 elseiftype(symbolsShape)=="table"then
 symShape={}
 fork,vinpairs(symbolsShape)do
 ifsymbolsShape[k]andshapes[symbolsShape[k]]then
 symShape[k]=shapes[symbolsShape[k]]
 else
 symShape[k]="circle"
 end
 end
 else
 symShape="circle"
 end
 -- symShapeScale 
 localsymShapeScale={}
 iftype(symShape)=="table"then
 symShapeScale=getSymShapeScale(symShape)
 table.insert(scales,symShapeScale)
 end

 -- custom stroke
 localsymStroke
 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
 ifsymbolsShape=="x"thensymStroke=2.5end
 --always draw x with stroke
 ifsymbolsNoFillthensymStroke=2.5end
 end


 --	TODO	-- symStrokeScale 
 --	 	local symStrokeScale = {}
 --		if type(symStroke) == "table" then
 --			symStrokeScale = getSymStrokeScale(symStroke)
 --			table.insert(scales, symStrokeScale)
 --		end



 localsymbolmarks=getSymbolMarks(chartmarks,symSize,symShape,symStroke,symbolsNoFill,alphaScale)
 ifchartmarks~=chartvisthen
 table.insert(chartvis.marks,symbolmarks)
 else
 table.insert(marks,symbolmarks)
 end
 end


 localvannolines,vannolabels,hannolines,hannolabels=getAnnoMarks(chartmarks,persistentGrey,persistentGrey,0.75)
 ifvannoDatathen
 table.insert(marks,vannolines)
 table.insert(marks,vannolabels)
 end
 ifhannoDatathen
 table.insert(marks,hannolines)
 table.insert(marks,hannolabels)
 end

 -- axes
 localxAxis,yAxis=getAxes(xTitle,xAxisFormat,xAxisAngle,xType,xGrid,yTitle,yAxisFormat,yType,yGrid,chartType)

 -- legend
 locallegend
 iflegendTitleandtonumber(legendTitle)~=0thenlegend=getLegend(legendTitle,chartType,outerRadius)end
 -- construct final output object
 localoutput=
 {
 version=2,
 width=graphwidth,
 height=graphheight,
 data={data},
 scales=scales,
 axes={xAxis,yAxis},
 marks=marks,
 legends={legend}
 }
 ifvannoDatathentable.insert(output.data,vannoData)end
 ifhannoDatathentable.insert(output.data,hannoData)end
 ifstatsthentable.insert(output.data,stats)end

 localflags
 ifformatJsonthenflags=mw.text.JSON_PRETTYend
 returnmw.text.jsonEncode(output,flags)
 end

 functionp.mapWrapper(frame)
 returnp.map(frame:getParent())
 end

 functionp.chartWrapper(frame)
 returnp.chart(frame:getParent())
 end

 functionp.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}},
 -- 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
 functionp.encodeTitleForPath(frame)
 returnmw.uri.encode(mw.text.decode(mw.text.trim(frame.args[1])),'PATH')
 end

 functionp.chartCompatible(frame)
 localnot_chart_args={
 "colors",
 "xAxisMin",
 "xAxisMax",
 "yAxisMin",
 "yAxisMax",
 "xAxisAngle",
 "xScaleType",
 "yScaleType",
 "linewidth",
 "linewidths",
 "showSymbols",
 "symbolsShape",
 "symbolsNoFill",
 "symbolsStroke",
 "showValues",
 "innerRadius",
 "xGrid",
 "yGrid",
 "annotations"
 }

 localpframe=frame:getParent()
 localb=0
 localt=0

 fort=1,18,1do
 ifpframe.args[not_chart_args[t]]then
 break
 else
 b=b+1
 end
 t=t+1
 end
 ifb==18then
 ifpframe.args["name"]then
 return"[[Category:Graphs to Port]]"
 else
 return"[[Category:Graphs to be ported needing names]]"
 end
 end
 end

 returnp

AltStyle によって変換されたページ (->オリジナル) /