7
$\begingroup$

I have a function which is a sum of three terms and I want to plot it in a DensityPlot. However, I would like that the ColorFunction would be the RGBColor resulting of the mixed R color corresponding to first term, G color of the second term and B color of the third term. I think that my problem is similar to that of combine RGB channels of a RGB image, but applied to an addition of three functions in a DensityPlot.

Any idea will be welcome. I have tried several things. However, as expected, I always could change only the color of the whole function as a function of z.

Thanks for your time.

Jose

$\endgroup$
2
  • $\begingroup$ Use Blend in your ColorFunction. $\endgroup$ Mar 12, 2015 at 18:47
  • $\begingroup$ @DavidG.Stork mathematica does not inject the coordinates into the ColorFunction. Only the function value, and that is not enough for what the OP wants to achieve $\endgroup$ Mar 12, 2015 at 19:01

3 Answers 3

8
$\begingroup$

Here is an example of how to do it:

f[x_, y_] := {Sin[x], Cos[y], Sin[2 x + y]}

Block[{x, y, h, xMin = -1, xMax = 3, yMin = -3, yMax = 3}, 
 Graphics[{}, PlotRange -> {{xMin, xMax}, {yMin, yMax}}, 
  Epilog -> Inset[Show[ColorCombine[Table[Image[
        DensityPlot[f[x, y][[i]], {x, xMin, xMax}, {y, yMin, yMax}, 
         Frame -> None, ImageMargins -> 0, PlotRangePadding -> None, 
         ColorFunction -> GrayLevel, ColorFunctionScaling -> None], 
        ColorSpace -> "Grayscale"], {i, 3}], "RGB"], 
     AspectRatio -> Full], {xMin, yMin}, {0, 0}, 
     {xMax - xMin, yMax - yMin}], Frame -> True, PlotRangePadding -> .08]]

colors

The main ingredient is to do the three function components as separate DensityPlots, then apply ColorCombine to them, and insert the resulting Image into a Graphics frame with the same coordinate range as the original function.

For the last part, I use Inset with its three optional arguments to insure the correct positioning and stretching. The stretching to the correct aspect ratio only works if I first apply Show with the option AspectRatio -> Full to the image that is to be inserted.

I also added ColorFunctionScaling->None to DensityPlot so that you have control over the maximum and minimum ranges of your color channels. In the table of DensityPlots, the color channel is first populated by GrayScale only. The colors are created by ColorCombine, but this only works for images with the colorspace specification "Grayscale".

$\endgroup$
7
  • $\begingroup$ I expected a gray scale from black to white for f[x_, y_] := {Sin[x], Sin@x, Sin@x}. It seems I have scaling issues. $\endgroup$ Mar 12, 2015 at 20:51
  • 1
    $\begingroup$ @belisarius Oh, yes - I messed up the use of ColorCombine. Let me fix it. Next time, I should look at the documentation before answering... $\endgroup$
    – Jens
    Mar 12, 2015 at 21:57
  • $\begingroup$ I just tried this code and got multiple errors of the type: Image::imgcsmsw: The specified color space GrayLevel and the number of channels 3 are not compatible; using Automatic instead. >> $\endgroup$
    – Mr.Wizard
    Mar 13, 2015 at 1:03
  • $\begingroup$ @Mr.Wizard it must be something in version 10 - I have version 8 right now and it works. I'll look at it when I can test in version 10... later today, I hope. $\endgroup$
    – Jens
    Mar 13, 2015 at 1:11
  • 1
    $\begingroup$ @Mr.Wizard Seems like Mathematica is trying to remove gray areas from its syntax for grey areas. $\endgroup$
    – Jens
    Mar 13, 2015 at 1:27
4
$\begingroup$

A possible alternative to DensityPlot is to render an Image:

(* kguler's example function *)
f[x_, y_] := {Sin[x] Sin[y], Sin[3 x] Cos[2 y], Cos[y/Pi] Sin[x + y]}


Array[f, {100, 100}, {{-2 Pi, 2 Pi}, {-2 Pi, 2 Pi}}] // Transpose // Reverse //
 Rescale // Image // ImageResize[#, 300] &

enter image description here


Here is a self-contained function that evaluates a function and plots it as a Raster, complete with axes:

plotAsRaster[
  fn_,
  points : {_, _} : {100, 100},
  ranges : {{_, _}, {_, _}},
  opts : OptionsPattern[Graphics]
] :=
   Graphics[
     Raster[Rescale@Array[fn, points, ranges]\[Transpose], ranges\[Transpose]], 
     opts, Frame -> True, AspectRatio -> 1
   ]

Test:

plotAsRaster[f, {{-2 Pi, 2 Pi}, {-2 Pi, 2 Pi}}]

enter image description here

(This is not intended to be a well developed function but merely a proof of concept.)

A modification with interpolation:

plotAsRasterInterpolated[fn_, points : {_, _} : {100, 100}, ranges : {{_, _}, {_, _}}, 
  opts : OptionsPattern[Graphics]] := 
 Graphics[Raster[
   ImageData@ImageResize[Image[Rescale@Array[fn, points, ranges]\[Transpose]], 3 points], 
   ranges\[Transpose]], opts, Frame -> True, AspectRatio -> 1, ImageSize -> 3 points]
$\endgroup$
4
  • $\begingroup$ Basically, that is what I did. However, I am also interested in showing the axes for more information about the plot content. $\endgroup$ Mar 13, 2015 at 7:51
  • $\begingroup$ @José Please see my update. I did not include interpolation in this example but if you find the idea otherwise pleasing I can include it. $\endgroup$
    – Mr.Wizard
    Mar 13, 2015 at 8:16
  • $\begingroup$ Nice solution. However, why as "raster"? It looses resolution. The alternative as Inset in Graphics seems to be good. $\endgroup$ Mar 17, 2015 at 12:42
  • $\begingroup$ @José It doesn't actually lose resolution, but it doesn't gain (apparent) resolution because I did not include interpolation. If that is included it will look smoother. I shall add an example to my answer. $\endgroup$
    – Mr.Wizard
    Mar 18, 2015 at 13:17
2
$\begingroup$
ClearAll[f]
f[x_, y_] := {Sin[x] Sin[y], Sin[3 x] Cos[2 y], Cos[y/Pi] Sin[ x + y]}

dp = DensityPlot[Plus @@ f[x, y], {x, -2 Pi, 2 Pi}, {y, -2 Pi, 2 Pi}, 
  Frame -> False, ImageSize -> 300]

enter image description here

dps = DensityPlot[f[x, y][[#]], {x, -2 Pi, 2 Pi}, {y, -2 Pi, 2 Pi}, 
     Frame -> False, ImageSize -> 300,
     ColorFunction -> (Function[{c}, RGBColor@RotateRight[{c, 0, 0}, # - 1]])] & /@ Range[3];
Row@dps

enter image description here

Fold[ImageAdd, dps]  (* thanks: Mr. Wizard *)
(* Fold[ImageAdd, First@dps, Rest@dps] in case the two-args version doesn't work *)

enter image description here

$\endgroup$
2
  • $\begingroup$ Your last line of code may be replaced with Fold[ImageAdd, dps] according to (54784). $\endgroup$
    – Mr.Wizard
    Mar 13, 2015 at 1:02
  • $\begingroup$ Thank you @Mr.Wizard - how quickly i forget:) $\endgroup$
    – kglr
    Mar 13, 2015 at 4:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.