ntg-context - mailing list for ConTeXt users
 help / color / mirror / Atom feed
* colors and contours in luametafun
@ 2021-09-01  7:54 Jacob Kauffmann via ntg-context
  2022-06-20 16:29 ` Jacob Kauffmann via ntg-context
  0 siblings, 1 reply; 3+ messages in thread
From: Jacob Kauffmann via ntg-context @ 2021-09-01  7:54 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: Jacob Kauffmann

[-- Attachment #1: Type: text/plain, Size: 2063 bytes --]

Dear list,

I am a huge fan of the new metafun interface.
Hans asked for luametafun requests, so here are a few.

 - color by value in lmt_surface
We want to show a surface plot of a function where the color indicates the function value (instead, or in addition to a light source).
The easiest would be to have variable cf for the brightness factor (as it is), and in addition variables such as zt, minz, maxz, akin to the color formatter for lmt_contour.
This becomes handy when colors are to be aligned with function values (e.g. negative = blue, zero = white, positive = red, see MWE attached).

 - controlling line levels in lmt_contour
It would be convenient if certain levels could be set by the user. E.g. to make sure the zero level contour line is included.
The user interface could potentially take a list, levels = { -1, -.5, 0, .5, 1 }, of contour level lines. See MWE attached.
From my understanding marching squares can do that. A possible reference implementation could be QuadContourGenerator [1] in matplotlib, a bit of description can be found in [2].

 - colormaps
Contour plots often use rather complex colormaps, such as jet, rainbow or veridis. They are optimized for perceptual resolution, color blindness, screen/print or certain use cases.
The functionality is already there, but from a user's perspective, it would be much easier if some of these were provided by the interface.
The interface could be color = "colormap('jet')(l/n)". Indeed, these are useful in other use cases as well, such as bar charts, surface plots or shades.
One rudimentary example is in the attached file.

 - number of levels in lmt_contour (potential bug)
The number of levels is different from the user's input. Depending on the output range it can be lower or higher (see MWE attached).

Cheers,
Jacob Kauffmann

[1] https://github.com/matplotlib/matplotlib/blob/96ff1146ad053c5c7481efd9de039c879a595968/src/_contour.cpp
[2] https://github.com/matplotlib/matplotlib/blob/96ff1146ad053c5c7481efd9de039c879a595968/src/_contour.h


[-- Attachment #2: colors_and_contours_in_luametafun.tex --]
[-- Type: application/octet-stream, Size: 2134 bytes --]

\starttext

\setupMPpage[
	offset=10pt,
	instance=doublefun]
	
\startluacode
-- function used in the examples
function fun(x,y)
	local exp = math.exp
	return 1.5*exp(-1.5*((x + 1.1)^2 + (y - 1.1)^2)) 
		 + 0.5*exp(-1.0*((x + 1)^2 + (y + 1)^2))
		 - 0.5*exp(-0.9*((x - 1)^2 + (y - 0)^2))
end

-- example of a simple blue-gray-red colormap
function colormap(f)
	local abs, min = math.abs, math.min
	local r, g, b = min(1, 2*f), 1-2*abs(f-.5), min(1,2-2*f)
	return .85*r, .85*g, .85*b
end
\stopluacode

\startMPpage
draw lmt_surface [
	code = "fun(x,y)",
	% here, I'd like to use something like
	% color = "colormap( 0.5 * fun(xt,yt) / max(abs(minz),abs(maxz)) + 0.5 )
	color = "colormap(f)",
	xmin = -3,
	xmax = 3,
	ymin = -3,
	ymax = 3,
	xstep = .3,
	ystep = .3,
	xvector = { -0.3, -0.5 },
	linecolor = 0
] xsized 10cm;
\stopMPpage

\startMPpage
label.rt(textext("all three plots are specified with {\tt levels = 7}"), (0, 4cm));

picture SixLevels;
SixLevels := lmt_contour [
	xmin = -3, xmax = 3, xstep = .05,
	ymin = -3, ymax = 3, ystep = .05,
	% would be nice to do something like
	% levels = {-1, -.5, 0, .5, 1}
	levels = 7,
	height = 3cm,
	function = "fun(x,y)",
	color = "colormap(l/n + .21)",
	linecolor = "black",
	legend = false,
	cache = true
];
draw SixLevels;
label.top(textext("six levels"), .5[ulcorner SixLevels, urcorner SixLevels]);

picture SevenLevels;
SevenLevels := lmt_contour [
	xmin = -3, xmax = 3, xstep = .05,
	ymin = -3, ymax = 3, ystep = .05,
	levels = 7,
	height = 3cm,
	function = "fun(x, y)*5",
	color = "colormap(l/n + .08)",
	linecolor = "black",
	legend = false,
	cache = true,
] xshifted 3.5cm;
draw SevenLevels;
label.top(textext("seven levels"), .5[ulcorner SevenLevels, urcorner SevenLevels]);

picture EightLevels;
EightLevels := lmt_contour [
	xmin = -3, xmax = 3, xstep = .05,
	ymin = -3, ymax = 3, ystep = .05,
	levels = 7,
	height = 3cm,
	function = "fun(x,y)*10",
	color = "colormap(l/n + .08)",
	linecolor = "black",
	legend = false,
	cache = true,
] xshifted 7cm;
draw EightLevels;
label.top(textext("eight levels"), .5[ulcorner EightLevels, urcorner EightLevels]);
\stopMPpage

\stoptext

[-- Attachment #3: colors_and_contours_in_luametafun.pdf --]
[-- Type: application/pdf, Size: 45989 bytes --]

[-- Attachment #4: Type: text/plain, Size: 493 bytes --]

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: colors and contours in luametafun
  2021-09-01  7:54 colors and contours in luametafun Jacob Kauffmann via ntg-context
@ 2022-06-20 16:29 ` Jacob Kauffmann via ntg-context
  2022-06-23 15:38   ` Hans Hagen via ntg-context
  0 siblings, 1 reply; 3+ messages in thread
From: Jacob Kauffmann via ntg-context @ 2022-06-20 16:29 UTC (permalink / raw)
  To: mailing list for ConTeXt users; +Cc: Jacob Kauffmann


[-- Attachment #1.1.1: Type: text/plain, Size: 3960 bytes --]

Dear list,

> Am 01.09.2021 um 09:54 schrieb Jacob Kauffmann via ntg-context <ntg-context@ntg.nl>:
> - color by value in lmt_surface
> We want to show a surface plot of a function where the color indicates the function value (instead, or in addition to a light source).
> The easiest would be to have variable cf for the brightness factor (as it is), and in addition variables such as zt, minz, maxz, akin to the color formatter for lmt_contour.
> This becomes handy when colors are to be aligned with function values (e.g. negative = blue, zero = white, positive = red, see MWE attached).

I managed to achieve this by tweaking f_color and mp.lmt_surface_do in mlib-cnt.lmt in
	ConTeXt  ver: 2022.05.11 11:36 LMTX  fmt: 2022.6.20
a bit.
Please find the diff and a MWE attached.

Cheers,
Jacob Kauffmann

--- context/tex/texmf-context/tex/context/base/mkxl/mlib-cnt.lmt   2022-06-20 18:11:51.000000000 +0200
+++ mlib-cnt.lmt        2022-06-20 18:26:22.000000000 +0200
@@ -1839,7 +1839,29 @@

 local f_color = formatters [ [[
     local math = math
-    return function(f)
+    local min  = math.min
+    local max  = math.max
+    local abs  = math.abs
+    local minz = %s
+    local maxz = %s
+
+    local color_value = 0
+    local color_step  = mp.lmt_color_functions.step
+    local color_shade = mp.lmt_color_functions.shade
+
+    local function step(...)
+        return color_step(color_value,n,...)
+    end
+    local function shade(...)
+        return color_shade(color_value,n,...)
+    end
+    -- local function lin(l)
+    --     return l/n
+    -- end
+    %s
+    return function(z, f)
+        function_value = z
+        brightness_factor = f
         return %s
     end
 ]] ]
@@ -1898,7 +1920,7 @@
     local dy   = (ymax - ymin) / ny
     local xt   = xmin
     --
-    local minf, maxf
+    local minf, maxf, minz, maxz
     --
     -- similar as contours but no data loop here
     --
@@ -1908,12 +1930,6 @@
         return false -- fatal error
     end
     --
-    local ccode = load(f_color(colorcode))
-    local color = type(ccode) == "function" and ccode()
-    if type(color) ~= "function" then
-        return false -- fatal error
-    end
-    --
     for i=0,nx do
         local yt = ymin
         for j=0,ny do
@@ -1946,7 +1962,16 @@
                 maxf = fac
             end
             --
-            data[i][j] = { x, y, fac }
+            if not minz then
+               minz = z
+               maxz = z
+            elseif z < minz then
+               minz = z
+            elseif z > maxz then
+               maxz = z
+            end
+            --
+            data[i][j] = { x, y, fac, z }
             --
             yt = yt + dy
         end
@@ -1957,6 +1982,16 @@
     local range   = maxf - minf
     local cl      = linecolor or 1
     local enforce = attributes.colors.model == "cmyk"
+    --
+    -- local ccode = load(f_color(colorcode))
+    report("minz, maxz is (%s,%s)",minz,maxz)
+    report("colorcode is %s", colorcode)
+    local ccode = load(f_color(minz, maxz, preamble, colorcode))
+    local color = type(ccode) == "function" and ccode()
+    if type(color) ~= "function" then
+        return false -- fatal error
+    end
+    --
     for i=0,nx-1 do
         for j=0,ny-1 do
             -- points
@@ -1985,12 +2020,13 @@
             local z32 = z3[2]
             local z41 = z4[1]
             local z42 = z4[2]
+            local zout = z1[4]
          -- if lines then
          --     -- fill first and draw then, previous shapes can be covered
          -- else
          --     -- fill and draw in one go to prevent artifacts
          -- end
-            local cr, cg, cb = color(cf)
+            local cr, cg, cb = color(zout, cf)
             if not cr then cr = 0 end
             if not cg then cg = 0 end
             if not cb then cb = 0 end


[-- Attachment #1.1.2: colors_and_surface_in_luametafun.pdf --]
[-- Type: application/pdf, Size: 17337 bytes --]

[-- Attachment #1.1.3: Type: text/plain, Size: 1 bytes --]



[-- Attachment #1.1.4: colors_and_surface_in_luametafun.tex --]
[-- Type: application/octet-stream, Size: 795 bytes --]

\starttext

\setupMPpage[
	offset=10pt,
	instance=doublefun]
	
\startluacode
-- function used in the examples
function fun(x,y)
	local exp = math.exp
	return 1.5*exp(-1.5*((x + 1.1)^2 + (y - 1.1)^2)) 
		 + 0.5*exp(-1.0*((x + 1)^2 + (y + 1)^2))
		 - 0.5*exp(-0.9*((x - 1)^2 + (y - 0)^2))
end

-- example of a simple blue-gray-red colormap
function colormap(f)
	local abs, min = math.abs, math.min
	local r, g, b = min(1, 2*f), 1-2*abs(f-.5), min(1,2-2*f)
	return .85*r, .85*g, .85*b
end
\stopluacode

\startMPpage
draw lmt_surface [
	code = "fun(x,y)",
	color = "colormap( 0.5 * z / max(abs(minz),abs(maxz)) + 0.5 )",
	% color = "colormap(f)",
	xmin = -3,
	xmax = 3,
	ymin = -3,
	ymax = 3,
	xstep = .3,
	ystep = .3,
	xvector = { -0.3, -0.5 },
	linecolor = 0
] xsized 10cm;
\stopMPpage

\stoptext

[-- Attachment #1.2: Message signed with OpenPGP --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 493 bytes --]

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: colors and contours in luametafun
  2022-06-20 16:29 ` Jacob Kauffmann via ntg-context
@ 2022-06-23 15:38   ` Hans Hagen via ntg-context
  0 siblings, 0 replies; 3+ messages in thread
From: Hans Hagen via ntg-context @ 2022-06-23 15:38 UTC (permalink / raw)
  To: Jacob Kauffmann via ntg-context; +Cc: Hans Hagen

On 6/20/2022 6:29 PM, Jacob Kauffmann via ntg-context wrote:
> Dear list,
> 
>> Am 01.09.2021 um 09:54 schrieb Jacob Kauffmann via ntg-context <ntg-context@ntg.nl>:
>> - color by value in lmt_surface
>> We want to show a surface plot of a function where the color indicates the function value (instead, or in addition to a light source).
>> The easiest would be to have variable cf for the brightness factor (as it is), and in addition variables such as zt, minz, maxz, akin to the color formatter for lmt_contour.
>> This becomes handy when colors are to be aligned with function values (e.g. negative = blue, zero = white, positive = red, see MWE attached).
> 
> I managed to achieve this by tweaking f_color and mp.lmt_surface_do in mlib-cnt.lmt in
> 	ConTeXt  ver: 2022.05.11 11:36 LMTX  fmt: 2022.6.20
> a bit.
> Please find the diff and a MWE attached.

in next version (next time just send me the file, easier than a diff)

> Cheers,
> Jacob Kauffmann
> 
> --- context/tex/texmf-context/tex/context/base/mkxl/mlib-cnt.lmt   2022-06-20 18:11:51.000000000 +0200
> +++ mlib-cnt.lmt        2022-06-20 18:26:22.000000000 +0200
> @@ -1839,7 +1839,29 @@
> 
>   local f_color = formatters [ [[
>       local math = math
> -    return function(f)
> +    local min  = math.min
> +    local max  = math.max
> +    local abs  = math.abs
> +    local minz = %s
> +    local maxz = %s
> +
> +    local color_value = 0
> +    local color_step  = mp.lmt_color_functions.step
> +    local color_shade = mp.lmt_color_functions.shade
> +
> +    local function step(...)
> +        return color_step(color_value,n,...)
> +    end
> +    local function shade(...)
> +        return color_shade(color_value,n,...)
> +    end
> +    -- local function lin(l)
> +    --     return l/n
> +    -- end
> +    %s
> +    return function(z, f)
> +        function_value = z
> +        brightness_factor = f
>           return %s
>       end
>   ]] ]
> @@ -1898,7 +1920,7 @@
>       local dy   = (ymax - ymin) / ny
>       local xt   = xmin
>       --
> -    local minf, maxf
> +    local minf, maxf, minz, maxz
>       --
>       -- similar as contours but no data loop here
>       --
> @@ -1908,12 +1930,6 @@
>           return false -- fatal error
>       end
>       --
> -    local ccode = load(f_color(colorcode))
> -    local color = type(ccode) == "function" and ccode()
> -    if type(color) ~= "function" then
> -        return false -- fatal error
> -    end
> -    --
>       for i=0,nx do
>           local yt = ymin
>           for j=0,ny do
> @@ -1946,7 +1962,16 @@
>                   maxf = fac
>               end
>               --
> -            data[i][j] = { x, y, fac }
> +            if not minz then
> +               minz = z
> +               maxz = z
> +            elseif z < minz then
> +               minz = z
> +            elseif z > maxz then
> +               maxz = z
> +            end
> +            --
> +            data[i][j] = { x, y, fac, z }
>               --
>               yt = yt + dy
>           end
> @@ -1957,6 +1982,16 @@
>       local range   = maxf - minf
>       local cl      = linecolor or 1
>       local enforce = attributes.colors.model == "cmyk"
> +    --
> +    -- local ccode = load(f_color(colorcode))
> +    report("minz, maxz is (%s,%s)",minz,maxz)
> +    report("colorcode is %s", colorcode)
> +    local ccode = load(f_color(minz, maxz, preamble, colorcode))
> +    local color = type(ccode) == "function" and ccode()
> +    if type(color) ~= "function" then
> +        return false -- fatal error
> +    end
> +    --
>       for i=0,nx-1 do
>           for j=0,ny-1 do
>               -- points
> @@ -1985,12 +2020,13 @@
>               local z32 = z3[2]
>               local z41 = z4[1]
>               local z42 = z4[2]
> +            local zout = z1[4]
>            -- if lines then
>            --     -- fill first and draw then, previous shapes can be covered
>            -- else
>            --     -- fill and draw in one go to prevent artifacts
>            -- end
> -            local cr, cg, cb = color(cf)
> +            local cr, cg, cb = color(zout, cf)
>               if not cr then cr = 0 end
>               if not cg then cg = 0 end
>               if not cb then cb = 0 end
> 
> 
> 
> 
> ___________________________________________________________________________________
> If your question is of interest to others as well, please add an entry to the Wiki!
> 
> maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
> webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
> archive  : https://bitbucket.org/phg/context-mirror/commits/
> wiki     : http://contextgarden.net
> ___________________________________________________________________________________


-- 

-----------------------------------------------------------------
                                           Hans Hagen | PRAGMA ADE
               Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
        tel: 038 477 53 69 | www.pragma-ade.nl | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://context.aanhet.net
archive  : https://bitbucket.org/phg/context-mirror/commits/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-06-23 15:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-01  7:54 colors and contours in luametafun Jacob Kauffmann via ntg-context
2022-06-20 16:29 ` Jacob Kauffmann via ntg-context
2022-06-23 15:38   ` Hans Hagen via ntg-context

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).