5
$\begingroup$

I would like to plot a figure with a top to bottom gradient like this: enter image description here

I drew this figure using Matlab. Is it possible to plot a similar one using Mathematica? I googled some posts, but I do not know how to do this. Is it possible to do it by "filling"? Thank you!

  1. According to Bob's idea, I tried this code:

     mx[x_] = -100*x*Exp[-69.3147*x^2]; (*This is my function*)
     Show[RegionPlot[
       mx[x] <= y <= 0 || 0 <= y <= mx[x], {x, -0.5, 0.5}, {y, -5.5, 5.5}, 
       ColorFunction -> "Rainbow", AspectRatio -> 0.75, 
       BoundaryStyle -> None], Plot[mx[x], {x, -0.5, 0.5}], 
      PlotStyle -> Directive[Darker[Blue], Thick]]
    

I got this figure: enter image description here

Why the right tail is incompleted? If we look the figure carefully, the peak position is also not perfectly match the curve.

  1. According to Michael's and kglr's idea, I tried this code:

     mx[t_] = t*Exp[-69.3147*t^2]; (*This is my function*)
     Get["https://pastebin.com/raw/gN4wGqxe"]
     JetCM = With[{colorlist = RGBColor @@@ jetColors}, 
        Blend[colorlist, #] &];
     ParametricPlot[{t, y*mx[t]}, {t, -0.5, 0.5}, {y, 0, 1}, 
       PlotRange -> All, 
       ColorFunction -> (JetCM[#2 + (25 #2^2 (#2 - 1/2) (1 - #2)^2)/(1 + 
               100 (#2 - 1/2)^2)] &), AspectRatio -> 0.75, Axes -> False, 
       BoundaryStyle -> {Thick, Black}] /. 
      Line[v_, opts___] :> Line[v[[2 ;; -2]], opts]
    

Then I got this figure: enter image description here The curve is not smooth anymore.

  1. By the way, how to fill an inverse raninbow color? I tried this:

     ColorFunction -> ColorData[{"Rainbow", "Reverse"}]
    

But it does not work.

$\endgroup$
2
  • $\begingroup$ A related example appears in the documentation, but it's in the other direction: Plot[Sin[x], {x, 0, 2 Pi}, ColorFunction -> Function[{x, y}, Hue[x]], Filling -> Axis, FillingStyle -> Automatic] $\endgroup$
    – flinty
    Jun 23, 2020 at 13:22
  • 2
    $\begingroup$ Increase the PlotPoints to get a smoother curve. $\endgroup$
    – flinty
    Jun 24, 2020 at 11:58

5 Answers 5

7
$\begingroup$

You can get the Matlab color scheme from this site, courtesy of @JasonB:

(*https://mathematica.stackexchange.com/a/64514/4999*)
Get["https://pastebin.com/raw/gN4wGqxe"]
JetCM = With[{colorlist = RGBColor @@@ jetColors}, 
   Blend[colorlist, #] &];

ParametricPlot[{s, t Sin[s]}, {s, 0, 2 Pi}, {t, 0, 1}, 
  ColorFunction -> (JetCM[#2 + (25 #2^2 (#2 - 1/2) (1 - #2)^2)/(
       1 + 100 (#2 - 1/2)^2)] &),
  AspectRatio -> 1, Axes -> False, 
  BoundaryStyle -> {Thick, Black}] /. 
 Line[v_, opts___] :> Line[v[[2 ;; -18]], opts]

It's probably easier just plotting sine twice and composing than to postprocess the boundary Line:

Show[
 ParametricPlot[{s, t Sin[s]}, {s, 0, 2 Pi}, {t, 0, 1}, 
  ColorFunction -> (JetCM[#2 + (25 #2^2 (#2 - 1/2) (1 - #2)^2)/(
       1 + 100 (#2 - 1/2)^2)] &), AspectRatio -> 1, Axes -> False, 
  BoundaryStyle -> None],
 Plot[Sin[s], {s, 0, 2 Pi}, PlotStyle -> {Thick, Black}]
 ]

I'm not sure how the Matlab scaling of the color gradient was done. It seemed to require some funky transformation to approximate the OP's image. One can simply use ColorFunction -> (JetCM[#2] &) if the exact gradient is not needed.

Both figures look like this:

$\endgroup$
5
  • $\begingroup$ Hi, Michael. Thank you for your methods. I tried your code, but the curve is not smooth anymore. Please see above, I just updated this post. :_) $\endgroup$
    – Mr.2023
    Jun 24, 2020 at 2:54
  • $\begingroup$ @Mr.2023 Increase PlotPoints. For example PlotPoints -> 30. (Probably don't need /. Line[v_, opts___] :> Line[v[[2 ;; -2]], opts]....or use something like /. Line[v_, opts___] :> Line[v[[2 ;; -32]], opts]) $\endgroup$
    – Michael E2
    Jun 24, 2020 at 3:02
  • $\begingroup$ Michael, it works. Now the curve becomes smooth.:-) Do you know how to fill an inverse Rainbow color? I mean that fill red color in down part and blue color up part. $\endgroup$
    – Mr.2023
    Jun 24, 2020 at 3:07
  • $\begingroup$ @Mr.2023 In the ColorFunction, the argument #2 is scaled to run from 0 to 1. So change each instance of #2 to 1 - #2. $\endgroup$
    – Michael E2
    Jun 24, 2020 at 3:09
  • $\begingroup$ Michael, Thank you for your help. Used your method, I got the final figure what I expected. :_) Have a nice day! $\endgroup$
    – Mr.2023
    Jun 24, 2020 at 3:14
5
$\begingroup$

Use RegionPlot for the filling

Show[
 RegionPlot[
  0 <= y <= Sin[x] && 0 <= x <= Pi ||
   Sin[x] <= y <= 0 && -Pi <= x <= 0,
  {x, -4, 4}, {y, -1.1, 1.1},
  ColorFunction -> "Rainbow",
  AspectRatio -> 0.75,
  BoundaryStyle -> None],
 Plot[Sin[x], {x, -Pi, Pi}],
 PlotStyle -> Directive[Darker[Blue], Thick]]

enter image description here

$\endgroup$
2
  • $\begingroup$ (+1), as this is more natural and faster than my DensityPlot. Also for the colour, try: ColorFunction -> Function[{x, y}, Hue[y]] to get a look closer to OP's question. $\endgroup$
    – flinty
    Jun 23, 2020 at 14:03
  • $\begingroup$ Hi, Bob. Thank you. I tried your method. It works but there exist some problems. Please see above, I just edit the post and show my progress.:_) $\endgroup$
    – Mr.2023
    Jun 24, 2020 at 2:21
5
$\begingroup$

It's possible to do this with a density plot if you're prepared to plug in the inequalities:

Show[
 DensityPlot[
  If[(0 < y < Sin[x]) || (Sin[x] < y < 0), y, ∞], {x, -π, π}, {y, -1, 1}, 
  ColorFunction -> Function[{x, y}, Hue[x]], PlotPoints -> 30]
 , Plot[Sin[x], {x, -π, π}, PlotStyle -> {Black, Thick}]
 ]

vertical filling effect

$\endgroup$
2
  • 2
    $\begingroup$ +1. You can also plot y and use e.g. RegionFunction -> Function[{x, y}, (y > 0 && y < Sin[x]) || (y < 0 && y > Sin[x])] $\endgroup$
    – C. E.
    Jun 23, 2020 at 14:46
  • $\begingroup$ Or you can use ConditionalExpression as well: ConditionalExpression[y, (0 < y < Sin[x]) || (Sin[x] < y < 0)] $\endgroup$
    – C. E.
    Jun 23, 2020 at 14:52
4
$\begingroup$
ParametricPlot[{x, t Sin[x]}, {x, -π, π}, {t, 0, 1},
 AspectRatio -> 1, 
 ColorFunction -> (ColorData["Rainbow"][#2] &),
 MeshFunctions -> {#4 &}, Mesh -> {{1}}, 
 MeshStyle -> Directive[Thick, Opacity[1], Black], Axes -> False, 
 BoundaryStyle -> None]

enter image description here

With the second example in OP:

mx[x_] := -100 x Exp[-69.3147*x^2];

ParametricPlot[{x, t mx[x]}, {x, -0.5, 0.5}, {t, 0, 1},
 AspectRatio -> 1, ColorFunction -> (ColorData["Rainbow"][#2] &),
 MeshFunctions -> {#4 &}, Mesh -> {{1}}, 
 MeshStyle -> Directive[Thick, Opacity[1], Black], Axes -> False, 
 BoundaryStyle -> None, PlotPoints -> 50, PlotRange -> All]

enter image description here

Use ColorFunction -> (ColorData[{"Rainbow", "Reverse"}][#2] &) to get

enter image description here

At the cost of some eye strain to find the right scaling ranges, we can use "VisibleSpectrum" to get close to the picture in OP:

colorFunction = ColorData["VisibleSpectrum"][
    If[# <= 0, Rescale[#, {-1, 0}, {450, 510}], Rescale[#, {0, 1}, {550, 660}]]] &;

ParametricPlot[{x, t Sin[x]}, {x, -π, π}, {t, 0, 1}, 
 AspectRatio -> 1,  
 ColorFunction -> (colorFunction[#2] &), 
 MeshFunctions -> {#4 &}, 
 Mesh -> {{1}}, 
 MeshStyle -> Directive[Thick, Opacity[1], Black], 
 ColorFunctionScaling -> False, 
 Axes -> False, 
 BoundaryStyle -> None]

enter image description here

And for the second example in OP:

colorFunction = ColorData["VisibleSpectrum"][If[# <= 0,
     Rescale[#, {-5, 0}, {450, 510}], Rescale[#, {0, 5}, {550, 660}]]] &;

ParametricPlot[{x, t mx[x]}, {x, -0.5, 0.5}, {t, 0, 1}, 
 AspectRatio -> 1, ColorFunction -> (colorFunction[#2] &), 
 MeshFunctions -> {#4 &}, Mesh -> {{1}}, 
 MeshStyle -> Directive[Thick, Opacity[1], Black], 
 ColorFunctionScaling -> False, Axes -> False, BoundaryStyle -> None, 
 PlotRange -> All, PlotPoints -> 50]

enter image description here

$\endgroup$
3
  • $\begingroup$ Hi, kglr. Thank you for your help. I tried the "ParametricPlot" method, but new problems apear. I just updated this post and show my progress of this problem. Could you read it and show me some possible solutions? :-) $\endgroup$
    – Mr.2023
    Jun 24, 2020 at 2:59
  • $\begingroup$ Hi, kglr. Thank you! I got it. :_) $\endgroup$
    – Mr.2023
    Jun 24, 2020 at 3:20
  • $\begingroup$ @Mr.2023, to get a smoother curve use a large value for PlotPoints, e.g.,PlotPoints -> 100. An for reversing the color function use ColorFunction -> (ColorData[{"Rainbow", "Reverse"}][#2] &). $\endgroup$
    – kglr
    Jun 24, 2020 at 3:20
2
$\begingroup$

We can also use a LinearGradientImage as the setting for PlotStyle:

mx[x_] := -100 x Exp[-69.3147*x^2];

ParametricPlot[{x, t mx[x]}, {x, -0.5, 0.5}, {t, 0, 1}, 
 AspectRatio -> 1, MeshFunctions -> {#4 &}, Mesh -> {{1}}, 
 MeshStyle -> Directive[Thick, Opacity[1], Black], Axes -> False, 
 BoundaryStyle -> None, PlotPoints -> 50, PlotRange -> All, 
 PlotStyle -> Opacity[1, Texture[LinearGradientImage[{Top, Bottom} -> "Rainbow"]]], 
 TextureCoordinateFunction -> ({#1, #2} &)]

enter image description here

Use LinearGradientImage[{Top, Bottom} -> ColorData[{"Rainbow", "Reversed"}]] or LinearGradientImage[{Bottom, Top} -> "Rainbow"] to get:

enter image description here

$\endgroup$
1
  • $\begingroup$ yes.Thank you:_) $\endgroup$
    – Mr.2023
    Jun 24, 2020 at 3:42

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.