I'll explain how to do this with ConTeXt + Lua. To keep the answer simple, I'll start by not considering the the "labels" of the rows and columns. I think that a good interface for this type of table is to be able to type:
\ProbabilityTable
{ { 4, 8, 12, 16 },
{ 3, 6, 9, 12 },
{ 2, 4, 6, 8 },
{ 1, 2, 3, 4 },
}
and get the desired result. So, lets start with the bare bones implementation so that this interface works. Since there is some flow-control and logic involved, I'll move all the calculations to Lua. So, at the TeX end, we simply need:
\unexpanded\def\ProbabilityTable#1%
{\ctxcommand{probability_table({#1})}}
where probability_table
(actually commands.probability_table
) is a Lua function that takes a 2-D Lua table and typesets it. The Lua part of the code is straight forward, so there are only a few comments in the code. Basically, we iterate over the lua-table, and then typeset it as a ConTeXt table.
\startluacode
-- Function that returns an index (low|medium|high) for an integer
local index = function(n)
local value = ""
if n <= 2 then
value = "low"
elseif n <= 7 then
value = "medium"
else
value = "high"
end
return value
end
-- Map values to colors
local colors = {
["low"] = "yellow",
["medium"] = "orange",
["high"] = "red",
}
-- Map values to labels
local labels = {
["low"] = "(Low)",
["medium"] = "(Med)",
["high"] = "(High)",
}
-- Print the probability table
probability_table = function(values)
-- Assume that values is a 2-D table:
context.bTABLE({"setups=probability:table"})
for row = 1,#values do
line = values[row]
context.bTR()
for col = 1, #line do
value = line[col]
idx = index(value)
options = { string.format("backgroundcolor=%s", colors[idx]) }
context.bTD(options)
context("%s \\crlf %s", value, labels[idx])
context.eTD()
end
context.eTR()
end
context.eTABLE()
end
-- Create a public interface
commands.probability_table = probability_table;
\stopluacode
Combining all this gives:
Now that the basic interface is working, we can take care of the formatting. For ConTeXt tables, this can be done by specifying a setup
and adding an interface to it (which is already done by "{setups=probability:table}" line in the lua code).
So, to get colors, add:
\startsetups probability:table
\setupTABLE[background=color]
\stopsetups
which gives:
Finally, to fix the alignment and formatting, add:
\startsetups probability:table
\setupTABLE[background=color]
\setupTABLE[align=middle, style=\ssbf, offset=0.5em]
\stopsetups
which gives
Adding row and column labels is left as a simple exercise for the reader :-)
. The labels are simply a new row and column with slightly different formatting.
The complete ConTeXt code is:
\startluacode
-- Function that returns an index (low|medium|high) for an integer
local index = function(n)
local value = ""
if n <= 2 then
value = "low"
elseif n <= 7 then
value = "medium"
else
value = "high"
end
return value
end
-- Map values to colors
local colors = {
["low"] = "yellow",
["medium"] = "orange",
["high"] = "red",
}
-- Map values to labels
local labels = {
["low"] = "(Low)",
["medium"] = "(Med)",
["high"] = "(High)",
}
-- Print the probability table
probability_table = function(values)
-- Assume that values is a 2-D table:
context.bTABLE({"setups=probability:table"})
for row = 1,#values do
line = values[row]
context.bTR()
for col = 1, #line do
value = line[col]
idx = index(value)
options = { string.format("backgroundcolor=%s", colors[idx]) }
context.bTD(options)
context("%s \\crlf %s", value, labels[idx])
context.eTD()
end
context.eTR()
end
context.eTABLE()
end
-- Create a public interface
commands.probability_table = probability_table;
\stopluacode
\unexpanded\def\ProbabilityTable#1%
{\ctxcommand{probability_table({#1})}}
\startsetups probability:table
\setupTABLE[background=color]
\setupTABLE[align=middle, style=\ssbf, offset=0.5em]
\stopsetups
\starttext
\ProbabilityTable
{ { 4, 8, 12, 16 },
{ 3, 6, 9, 12 },
{ 2, 4, 6, 8 },
{ 1, 2, 3, 4 },
}
\stoptext
Note that:
There is a nice separation between content and presentation. You can easily change the formatting by changing the probability:table
setup.
It is easy to change how the result is shown by changing the labels
and colors
tables. This can be made configurable at the TeX end as well.
I find it easier to program in Lua rather than in TeX.
ConTeXt provides a nice lua interface for the TeX macros. So, you can use context.bTABLE()
rather than tex.print("\\bTABLE")
, etc.
EDIT: Heiko Oberdiek mentioned that the cell background should not completely fill the cell. To achieve that in ConTeXt, add backgroundoffset=<dimen>
to the table settings. For example, with:
\startsetups probability:table
\setupTABLE[background=color, backgroundoffset=-1pt]
\setupTABLE[align=middle, style=\ssbf, offset=0.5em]
\stopsetups
you get: