4
$\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$
  • $\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 at 13:22
  • 2
    $\begingroup$ Increase the PlotPoints to get a smoother curve. $\endgroup$ – flinty Jun 24 at 11:58
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:

| improve this answer | |
$\endgroup$
  • $\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 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 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 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 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 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

| improve this answer | |
$\endgroup$
  • $\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 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 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

| improve this answer | |
$\endgroup$
  • 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 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 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

| improve this answer | |
$\endgroup$
  • $\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 at 2:59
  • $\begingroup$ Hi, kglr. Thank you! I got it. :_) $\endgroup$ – Mr.2023 Jun 24 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 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

| improve this answer | |
$\endgroup$
  • $\begingroup$ yes.Thank you:_) $\endgroup$ – Mr.2023 Jun 24 at 3:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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